package labox.innovation.gameserver.model.actor.instance;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javolution.util.FastList;
import javolution.util.FastMap;
import labox.innovation.config.Config;
import labox.innovation.db.CombatSetDAO;
import labox.innovation.db.ItemsDb;
import labox.innovation.db.PlayerDb;
import labox.innovation.db.PlayerQuest;
import labox.innovation.db.PlayerSkills;
import labox.innovation.db.PropGrantDAO;
import labox.innovation.db.PlayerDb.UpdateOnlineStatus;
import labox.innovation.gameserver.GameTimeController;
import labox.innovation.gameserver.GmListTable;
import labox.innovation.gameserver.ItemsAutoDestroy;
import labox.innovation.gameserver.LoginServerThread;
import labox.innovation.gameserver.ThreadPoolManager;
import labox.innovation.gameserver.ai.CtrlIntention;
import labox.innovation.gameserver.ai.L2PlayerAI;
import labox.innovation.gameserver.ai.L2SummonAI;
import labox.innovation.gameserver.cache.HtmCache;
import labox.innovation.gameserver.communitybbs.BB.Forum;
import labox.innovation.gameserver.datatables.AccessLevels;
import labox.innovation.gameserver.datatables.AdminCommandAccessRights;
import labox.innovation.gameserver.datatables.ItemTable;
import labox.innovation.gameserver.datatables.NpcTemplateTable;
import labox.innovation.gameserver.handler.AdminCommandHandler;
import labox.innovation.gameserver.handler.IAdminCommandHandler;
import labox.innovation.gameserver.handler.IItemHandler;
import labox.innovation.gameserver.handler.ItemHandler;
import labox.innovation.gameserver.instancemanager.CoupleManager;
import labox.innovation.gameserver.instancemanager.InstanceManager;
import labox.innovation.gameserver.instancemanager.ItemsOnGroundManager;
import labox.innovation.gameserver.instancemanager.QuestManager;
import labox.innovation.gameserver.model.BlockList;
import labox.innovation.gameserver.model.ConsignmentManager;
import labox.innovation.gameserver.model.DropItemSelectInterface;
import labox.innovation.gameserver.model.ForgeItemList;
import labox.innovation.gameserver.model.FriendInstance;
import labox.innovation.gameserver.model.FriendNewsFactory;
import labox.innovation.gameserver.model.FuzeSkillCoolDown;
import labox.innovation.gameserver.model.FuzeWorld;
import labox.innovation.gameserver.model.ItemDropManage;
import labox.innovation.gameserver.model.L2AccessLevel;
import labox.innovation.gameserver.model.L2Clan;
import labox.innovation.gameserver.model.L2ClanMember;
import labox.innovation.gameserver.model.L2Effect;
import labox.innovation.gameserver.model.L2FriendsNewsManager;
import labox.innovation.gameserver.model.L2ItemInstance;
import labox.innovation.gameserver.model.L2Object;
import labox.innovation.gameserver.model.L2Party;
import labox.innovation.gameserver.model.L2PetData;
import labox.innovation.gameserver.model.L2PetDataTable;
import labox.innovation.gameserver.model.L2Radar;
import labox.innovation.gameserver.model.L2Request;
import labox.innovation.gameserver.model.L2ShortCut;
import labox.innovation.gameserver.model.L2Skill;
import labox.innovation.gameserver.model.L2Transformation;
import labox.innovation.gameserver.model.PkIntance;
import labox.innovation.gameserver.model.Punish;
import labox.innovation.gameserver.model.ShortCuts;
import labox.innovation.gameserver.model.TradeList;
import labox.innovation.gameserver.model.FuzeSkillCoolDown.TimeStamp;
import labox.innovation.gameserver.model.L2Skill.SkillTargetType;
import labox.innovation.gameserver.model.actor.L2Attackable;
import labox.innovation.gameserver.model.actor.L2Character;
import labox.innovation.gameserver.model.actor.L2Decoy;
import labox.innovation.gameserver.model.actor.L2Npc;
import labox.innovation.gameserver.model.actor.L2Playable;
import labox.innovation.gameserver.model.actor.L2Summon;
import labox.innovation.gameserver.model.actor.L2Trap;
import labox.innovation.gameserver.model.actor.appearance.PcAppearance;
import labox.innovation.gameserver.model.actor.knownlist.PcKnownList;
import labox.innovation.gameserver.model.actor.position.PcPosition;
import labox.innovation.gameserver.model.actor.stat.PcStat;
import labox.innovation.gameserver.model.actor.status.PcStatus;
import labox.innovation.gameserver.model.base.ClassId;
import labox.innovation.gameserver.model.base.PracticeId;
import labox.innovation.gameserver.model.base.Race;
import labox.innovation.gameserver.model.entity.Instance;
import labox.innovation.gameserver.model.itemcontainer.Inventory;
import labox.innovation.gameserver.model.itemcontainer.ItemContainer;
import labox.innovation.gameserver.model.itemcontainer.PcFreight;
import labox.innovation.gameserver.model.itemcontainer.PcInventory;
import labox.innovation.gameserver.model.itemcontainer.PcWarehouse;
import labox.innovation.gameserver.model.listener.INpcFaceStateListenr;
import labox.innovation.gameserver.model.quest.Quest;
import labox.innovation.gameserver.model.quest.QuestState;
import labox.innovation.gameserver.model.quest.State;
import labox.innovation.gameserver.model.quest.Quest.QuestEventType;
import labox.innovation.gameserver.model.quest.QuestStateLogic.QuestCompletedStatus;
import labox.innovation.gameserver.model.quest.dataset.QuestDataSet;
import labox.innovation.gameserver.network.L2GameClient;
import labox.innovation.gameserver.network.SystemMessageId;
import labox.innovation.gameserver.network.clientpackets.Say2;
import labox.innovation.gameserver.network.serverpackets.ActionFailed;
import labox.innovation.gameserver.network.serverpackets.CharInfo;
import labox.innovation.gameserver.network.serverpackets.InventoryUpdate;
import labox.innovation.gameserver.network.serverpackets.ItemList;
import labox.innovation.gameserver.network.serverpackets.L2GameServerPacket;
import labox.innovation.gameserver.network.serverpackets.LeaveWorld;
import labox.innovation.gameserver.network.serverpackets.PartySmallWindowUpdate;
import labox.innovation.gameserver.network.serverpackets.PcSkillTree;
import labox.innovation.gameserver.network.serverpackets.SceneMap;
import labox.innovation.gameserver.network.serverpackets.StatusUpdate;
import labox.innovation.gameserver.network.serverpackets.SystemMessage;
import labox.innovation.gameserver.network.serverpackets.TeleportToLocation;
import labox.innovation.gameserver.network.serverpackets.TradeDone;
import labox.innovation.gameserver.network.serverpackets.TradeStart;
import labox.innovation.gameserver.network.serverpackets.TradeStats;
import labox.innovation.gameserver.templates.chars.NpcTemplate;
import labox.innovation.gameserver.templates.chars.PlayerTemplate;
import labox.innovation.gameserver.templates.item.FuzeEconomicManager;
import labox.innovation.gameserver.templates.item.L2Armor;
import labox.innovation.gameserver.templates.item.L2ArmorType;
import labox.innovation.gameserver.templates.item.L2Item;
import labox.innovation.gameserver.templates.item.L2Weapon;
import labox.innovation.gameserver.templates.item.L2WeaponType;
import labox.innovation.gameserver.templates.item.FuzeEconomicManager.OPSTATE;
import labox.innovation.gameserver.templates.skills.L2EffectType;
import labox.innovation.gameserver.templates.skills.L2SkillType;
import labox.innovation.gameserver.timer.Timer;
import labox.innovation.gameserver.util.FloodProtectors;
import labox.innovation.gameserver.util.Util;
import labox.innovation.util.Point2D;

/**
 * This class represents all player characters in the world. There is always a client-thread connected to this (except if a player-store is activated upon logout).<BR>
 * <BR>
 * 
 * @version $Revision: 1.66.2.41.2.33 $ $Date: 2005/04/11 10:06:09 $
 */
public final class FuzePcInstance extends L2Playable {

	public static final int REQUEST_TIMEOUT = 15;

	public static final int STORE_PRIVATE_NONE = 0;

	public static final int STORE_PRIVATE_SELL = 1;

	public static final int STORE_PRIVATE_BUY = 3;

	public static final int STORE_PRIVATE_MANUFACTURE = 5;

	public static final int STORE_PRIVATE_PACKAGE_SELL = 8;

	/**
	 * List of all QuestState instance that needs to be notified of this L2PcInstance's or its pet's death
	 */
	private List<QuestState> _NotifyQuestOfDeathList = new FastList<QuestState>();

	public class AIAccessor extends L2Character.AIAccessor {
		protected AIAccessor() {

		}

		public FuzePcInstance getPlayer() {
			return FuzePcInstance.this;
		}

		public void doPickupItem(L2Object object) {
			FuzePcInstance.this.doPickupItem(object);
		}

		public void doInteract(L2Character target) {
			FuzePcInstance.this.doInteract(target);
		}

		@Override
		public void doAttack(L2Character target) {
			super.doAttack(target);
		}

		@Override
		public void doCast(L2Skill skill) {
			super.doCast(skill);
		}
	}

	/**
	 * 关于所有好友的操作类
	 */
	private FriendInstance friendInstance = new FriendInstance(this);

	public FriendInstance getFriendInstance() {
		return friendInstance;
	}

	// 角色的PK模式
	private PkIntance pkInstance = new PkIntance(this);

	public PkIntance getPkInstance() {
		return pkInstance;
	}

	/**
	 * 角色对象所连接的客户端对象
	 */
	private L2GameClient _client;

	/**
	 * 角色对象的账户名
	 */
	private String _accountName;

	/**
	 * 角色的删除时间
	 */
	private long _deleteTimer;

	/**
	 * 角色对象的在线状态
	 */
	private boolean _isOnline;

	/**
	 * 角色的在线时间
	 */
	private long _onlineTime;

	private long _onlineBeginTime;

	private long _lastAccess;

	private long _uptime;

	/**
	 * 雷达对象
	 */
	private L2Radar _radar = new L2Radar(this);

	public L2Radar getRadar() {
		return _radar;
	}

	protected int _activeClass;

	/** data for mounted pets */
	private int _controlItemId;

	private L2PetData _data;

	private int _curFeed;

	protected Timer _mountFeedTask;

	/**
	 * 角色外形容貌对象
	 */
	private PcAppearance _appearance;

	/**
	 * 玩家的善恶值
	 */
	private int _karma;

	public static enum KarmaStat {
		/**
		 * 侠义
		 */
		ERRANTRY,
		/**
		 * 邪恶
		 */
		EVIL,
		/**
		 * 侵袭
		 */
		ATTACK
	}

	// clien
	private final FloodProtectors _floodProtectors = new FloodProtectors(this);

	private Punish _punish = new Punish(this);

	/**
	 * 记录玩家最近一次聊天时间
	 */
	private long _lastChatTime = 0;

	private int _mountType;

	private int _mountNpcId;

	private int _mountLevel;

	/** Store object used to summon the strider you are mounting **/
	private long _mountObjectID;

	public boolean _exploring;

	private L2Transformation _transformation;

	private static int _transformationId;

	private static final StringBuilder _logSb = new StringBuilder();

	/**
	 * 背包对象
	 */
	private PcInventory _inventory = new PcInventory(this);

	// 技能冷却管理器
	private FuzeSkillCoolDown _skillCoolDown = new FuzeSkillCoolDown(this);

	private PcWarehouse _warehouse;// 仓库对象

	private PcFreight _freight;

	private List<PcFreight> _depositedFreight;

	private TradeList _activeTradeList;

	private ForgeItemList _activeForgeList;

	private ItemContainer _activeWarehouse;

	/**
	 * The L2FolkInstance corresponding to the last Folk wich one the player talked.
	 */
	private L2Npc _lastFolkNpc;

	/** 在任务中最后一个对话的NPC */
	private long _questNpcObject;

	/**
	 * NPC表情状态监听容器
	 */
	private FastList<INpcFaceStateListenr> _npcFaceStateListeners = new FastList<INpcFaceStateListenr>();

	/**
	 * 注册NPC表情状态监听器
	 * 
	 * @param listner
	 */
	public void registerNpcStateListener(INpcFaceStateListenr listner) {
		if (!_npcFaceStateListeners.contains(listner))
			_npcFaceStateListeners.add(listner);
	}

	/**
	 * 注销NPC表情状态监听器
	 * 
	 * @param listner
	 */
	public void unRegisterNpcStateListener(INpcFaceStateListenr listner) {
		_npcFaceStateListeners.remove(listner);
	}

	/**
	 * 获取当前玩家注册NPC表情状态监听器列表
	 * @return
	 */
	public FastList<INpcFaceStateListenr> getNpcFaceStateListeners() {
		return this._npcFaceStateListeners;
	}

	/** 人物的所有任务表 */
	private Map<String, QuestState> _quests = new FastMap<String, QuestState>();

	/** 人物快捷方式数据列表 */
	private ShortCuts _shortCuts = new ShortCuts(this);

	/** The L2Summon of the L2PcInstance */
	private L2Summon _summon;

	/** The L2Decoy of the L2PcInstance */
	private L2Decoy _decoy;

	/** The L2Trap of the L2PcInstance */
	private L2Trap _trap;

	// Clan related attributes
	/** The Clan Identifier of the L2PcInstance */
	private long _clanId;

	/** The Clan object of the L2PcInstance */
	private L2Clan _clan;

	/** Apprentice and Sponsor IDs */
	private int _apprentice;

	private int _sponsor;

	private long _clanJoinExpiryTime;

	private long _clanCreateExpiryTime;

	private int _clanPrivileges;

	/**
	 * 释放在地图上的技能的坐标
	 */
	private Point2D _currentSkillWorldPosition;

	/**
	 * 此角色连接服务器的特权等级
	 */
	private L2AccessLevel _accessLevel;

	private boolean _messageRefusal; // message refusal mode

	private boolean _tradeRefusal; // Trade refusal

	/**
	 * 角色加入的队伍对象
	 */
	private L2Party _party;

	// this is needed to find the inviting player for Party response
	// there can only be one active party request at once
	private FuzePcInstance _activeRequester;

	private long _requestExpireTime;

	private L2Request _request = new L2Request(this);

	/**
	 * 在场景跳转结束后的保护时间
	 */
	private long _protectEndTime;

	/**
	 * 当手中没有武器时的默认武器模板
	 */
	private L2Weapon _fistsWeaponItem;

	/**
	 * 此角色账户的所有角色表
	 */
	private final Map<Long, String> _chars = new FastMap<Long, String>();

	/**
	 * 背包对象是否禁止的标记
	 */
	protected boolean _inventoryDisable;

	/** Event parameters */
	public int eventWorldID;

	public int eventX;

	public int eventY;

	public int eventkarma;

	public int eventpkkills;

	public String eventTitle;

	public LinkedList<String> kills = new LinkedList<String>();

	public boolean eventSitForced;

	public boolean atEvent;

	private final BlockList _blockList = new BlockList();

	private int[] _transformAllowedSkills;

	private Forum _forumMail;

	/**
	 * Current skill in use. Note that L2Character has _lastSkillCast, but this has the button presses
	 */
	private SkillDat _currentSkill;

	private SkillDat _currentPetSkill;

	/** Skills queued because a skill is already in progress */
	private SkillDat _queuedSkill;

	private int _reviveRequested;

	private boolean _revivePet;

	/**
	 * 上次玩家原地复活的时间
	 */
	private int _previousSituReviveTime;

	/**
	 * 设置上次玩家原地复活的时间
	 * 
	 * @param time
	 */
	public void setPreviousSituReviveTime(int time) {
		_previousSituReviveTime = time;
	}

	/**
	 * 玩家原地复活的花费
	 */
	private int _situReviveCost;

	/**
	 * 获得玩家原地复活的花费
	 * 
	 * @return
	 */
	public int getSituReviveCost() {
		return _situReviveCost;
	}

	/**
	 * 设置玩家原地复活的花费
	 * 
	 * @param time
	 */
	public void setSituReviveCost(int cost) {
		_situReviveCost = cost;
	}

	/**
	 * 获得上次玩家原地复活的时间
	 * 
	 * @return
	 */
	public int getPreviousSituReviveTime() {
		return _previousSituReviveTime;
	}

	/**
	 * 监听当前玩家所有聊天信息的GM列表
	 */
	private List<FuzePcInstance> _snoopListener;

	/**
	 * 当前GM监听的玩家列表
	 */
	private List<FuzePcInstance> _snoopedPlayer;

	/**
	 * 玩家是否已经结婚
	 */
	private boolean _married;

	private long _partnerId;

	private long _coupleId;

	private boolean _engagerequest;

	private int _engageid;

	private boolean _marryrequest;

	private boolean _marryaccepted;

	private byte _pvpFlag;

	private int _pvpKills;

	private int _pkKills;

	public boolean isAutoAttack;

	private String _autoPK;

	public int _shortBuffTaskSkillId;

	/**
	 * 召唤出的驯化的野兽
	 */
	private L2TamedBeastInstance _tamedBeast;

	/**
	 * 玩家的仙魔位枚举
	 */
	private PracticeId _practice;

	/**
	 * 包含了这种任务类型的任务表,只针对玩家本身所包含的任务事件
	 */
	private Map<Quest.QuestEventType, Set<String>> _questEvents;

	/**
	 * 任务数据:用于保存任务数据
	 */
	private List<PlayerQuestValues> _questValues = new ArrayList<PlayerQuestValues>();

	/**
	 * 任务提示消息(脚本使用)
	 */
	public String questMSG;

	/**
	 * 玩家可接任务列表
	 */
	private Set<String> _mayAccepyQuestList = new HashSet<String>();

	/**
	 * 玩家已接(未完成)任务列表
	 */
	private Set<String> _accepyQuestList = new HashSet<String>();

	/**
	 * 数据库读取当前HP
	 */
	private int _currentHpTem;

	/**
	 * 数据库读取当前MP
	 */
	private int _currentMpTem;

	public int getCurrentHpTem() {
		return _currentHpTem;
	}

	public void setCurrentHpTem(int currentHpTem) {
		_currentHpTem = currentHpTem;
	}

	public int getCurrentMpTem() {
		return _currentMpTem;
	}

	public void setCurrentMpTem(int currentMpTem) {
		_currentMpTem = currentMpTem;
	}

	/**
	 * 聊天、系统消息频道开关设置
	 */
	private short chatSwitches = 0x7fff;

	public short getChatSwitches() {
		return this.chatSwitches;
	}

	public void setChatSwitches(short chatSwitches) {
		this.chatSwitches = chatSwitches;
	}

	/**
	 * 根据聊天频道的代码获取当前聊天频道是否可用
	 * 
	 * @param code
	 * @return
	 */
	public boolean getSwitchByChatCode(byte code) {
		boolean result = true;
		result = (((this.chatSwitches & 0xffff) & (0x0001 << code)) > 0);
		return result;
	}

	/**
	 * Skill casting information (used to queue when several skills are cast in a short time)
	 **/
	// 技能释放信息
	// 当多个技能在同时使用时 用来排队技能
	public class SkillDat {
		private L2Skill _skill;

		private boolean _ctrlPressed;

		private boolean _shiftPressed;

		protected SkillDat(L2Skill skill, boolean ctrlPressed, boolean shiftPressed) {
			_skill = skill;
			_ctrlPressed = ctrlPressed;
			_shiftPressed = shiftPressed;
		}

		public boolean isCtrlPressed() {
			return _ctrlPressed;
		}

		public boolean isShiftPressed() {
			return _shiftPressed;
		}

		public L2Skill getSkill() {
			return _skill;
		}

		public int getSkillId() {
			return (getSkill() != null) ? getSkill().getId() : -1;
		}
	}

	// summon friend
	private summonRequest _summonRequest = new summonRequest();

	public class summonRequest {
		private FuzePcInstance _target = null;

		private L2Skill _skill = null;

		public void setTarget(FuzePcInstance destination, L2Skill skill) {
			_target = destination;
			_skill = skill;
		}

		public FuzePcInstance getTarget() {
			return _target;
		}

		public L2Skill getSkill() {
			return _skill;
		}
	}

	/**
	 * Constructor of L2PcInstance (use L2Character constructor).<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Call the L2Character constructor to create an empty _skills slot and copy basic Calculator set to this L2PcInstance</li> <li>Set the name of the L2PcInstance</li><BR>
	 * <BR>
	 * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method SET the level of the L2PcInstance to 1</B></FONT><BR>
	 * <BR>
	 * 
	 * @param objectId
	 *            Identifier of the object to initialized
	 * @param template
	 *            The L2PcTemplate to apply to the L2PcInstance
	 * @param accountName
	 *            The name of the account including this L2PcInstance
	 */
	public FuzePcInstance(long objectId, PlayerTemplate template, String accountName, PcAppearance app) {
		super(objectId, template);
		// super.initCharStatusUpdateValues();
		// initPcStatusUpdateValues();

		_accountName = accountName;
		app.setOwner(this);
		_appearance = app;

		// Create an AI
		_ai = new L2PlayerAI(new FuzePcInstance.AIAccessor());

		registerNpcStateListener(_radar);
	}

	/**
	 * Create a new L2PcInstance and add it in the characters table of the database.<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Create a new L2PcInstance with an account name</li> <li>Set the name, the Hair Style, the Hair Color and the Face type of the L2PcInstance</li> <li>Add the player in the characters table of the database</li><BR>
	 * <BR>
	 * 
	 * @param objectId
	 *            Identifier of the object to initialized
	 * @param template
	 *            The L2PcTemplate to apply to the L2PcInstance
	 * @param accountName
	 *            The name of the L2PcInstance
	 * @param name
	 *            The name of the L2PcInstance
	 * @param hairStyle
	 *            The hair style Identifier of the L2PcInstance
	 * @param hairColor
	 *            The hair color Identifier of the L2PcInstance
	 * @param face
	 *            The face type Identifier of the L2PcInstance
	 * @return The L2PcInstance added to the database or null
	 */
	public static FuzePcInstance create(long objectId, PlayerTemplate template, String accountName, String name, int sex) {
		// 用账户名创建一个角色
		PcAppearance app = new PcAppearance(sex);
		FuzePcInstance player = new FuzePcInstance(objectId, template, accountName, app);
		// 设置角色名称
		player.setName(name);
		// 在数据库的角色表中添加角色
		boolean ok = player.createDb();
		if (!ok) {
			return null;
		}
		return player;
	}

	public String getAccountName() {
		if (getClient() == null || getClient().isDetached())
			return _accountName;
		return getClient().getAccountName();
	}

	public Map<Long, String> getAccountChars() {
		return _chars;
	}

	public int getRelation(FuzePcInstance target) {
		int result = 0;

		// if (getClan() != null)//如果是一个家族成员
		// result |= RelationChanged.RELATION_CLAN_MEMBER;
		// if (isClanLeader())//如果是家族领袖
		// result |= RelationChanged.RELATION_LEADER;
		// if (getParty() != null && getParty() == target.getParty()) {
		// result |= RelationChanged.RELATION_HAS_PARTY;
		// for (int i = 0; i < getParty().getPartyMembers().size(); i++) {
		// if (getParty().getPartyMembers().get(i) != this)
		// continue;
		// switch (i) {
		// case 0:
		// result |= RelationChanged.RELATION_PARTYLEADER; // 0x10
		// break;
		// case 1:
		// result |= RelationChanged.RELATION_PARTY4; // 0x8
		// break;
		// case 2:
		// result |= RelationChanged.RELATION_PARTY3 +
		// RelationChanged.RELATION_PARTY2 + RelationChanged.RELATION_PARTY1; //
		// 0x7
		// break;
		// case 3:
		// result |= RelationChanged.RELATION_PARTY3 +
		// RelationChanged.RELATION_PARTY2; // 0x6
		// break;
		// case 4:
		// result |= RelationChanged.RELATION_PARTY3 +
		// RelationChanged.RELATION_PARTY1; // 0x5
		// break;
		// case 5:
		// result |= RelationChanged.RELATION_PARTY3; // 0x4
		// break;
		// case 6:
		// result |= RelationChanged.RELATION_PARTY2 +
		// RelationChanged.RELATION_PARTY1; // 0x3
		// break;
		// case 7:
		// result |= RelationChanged.RELATION_PARTY2; // 0x2
		// break;
		// case 8:
		// result |= RelationChanged.RELATION_PARTY1; // 0x1
		// break;
		// }
		// }
		// }
		//
		// if (getClan() != null && target.getClan() != null) {
		// if (target.getClan().isAtWarWith(getClan().getClanId())) {
		// result |= RelationChanged.RELATION_1SIDED_WAR;
		// if (getClan().isAtWarWith(target.getClan().getClanId()))
		// result |= RelationChanged.RELATION_MUTUAL_WAR;
		// }
		// }
		return result;
	}

	/**
	 * Retrieve a L2PcInstance from the characters table of the database and add it in _allObjects of the L2world (call restore method).<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Retrieve the L2PcInstance from the characters table of the database</li> <li>Add the L2PcInstance object in _allObjects</li> <li>Set the x,y,z position of the L2PcInstance and make it invisible</li> <li>Update the overloaded status of the L2PcInstance</li><BR>
	 * <BR>
	 * 
	 * @param objectId
	 *            Identifier of the object to initialized
	 * @return The L2PcInstance loaded from the database
	 */
	public static FuzePcInstance load(long objectId) {
		return restore(objectId);
	}

	// private void initPcStatusUpdateValues() {
	// _mpUpdateInterval = getMaxMp() / _barPixels;
	// _mpUpdateIncCheck = getMaxMp();
	// _mpUpdateDecCheck = getMaxMp() - _mpUpdateInterval;
	// }

	@Override
	public final PcKnownList getKnownList() {
		return (PcKnownList) _knownList;
	}

	@Override
	public void initKnownList() {
		setKnownList(new PcKnownList(this));
	}

	@Override
	public PcStat getStat() {
		return (PcStat) _stat;
	}

	@Override
	public void initCharStat() {
		setStat(new PcStat(this));
	}

	@Override
	public final PcStatus getStatus() {
		return (PcStatus) _status;
	}

	@Override
	public void initCharStatus() {
		setStatus(new PcStatus(this));
	}

	@Override
	public PcPosition getPosition() {
		return (PcPosition) _position;
	}

	@Override
	public void initPosition() {
		setObjectPosition(new PcPosition(this));
	}

	public final PcAppearance getAppearance() {
		return _appearance;
	}

	/** Return the L2PcTemplate link to the L2PcInstance. */
	@Override
	public final PlayerTemplate getTemplate() {
		return (PlayerTemplate) _template;
	}

	@Override
	public void initAI() {
		_ai = new L2PlayerAI(new FuzePcInstance.AIAccessor());
	}

	/**
	 * Return the AI of the L2PcInstance (create it if necessary).<BR>
	 * <BR>
	 */
	@Override
	public L2PlayerAI getAI() {
		return (L2PlayerAI) _ai;
	}

	/** 返回L2PcInstance的等级. */
	@Override
	public final int getLevel() {
		return getStat().getLevel();
	}

	/*-----------------------------任务处理部分------------------------------------*/

	/**
	 * 返回最后一次谈话的NPC对象id.<BR>
	 * <BR>
	 */
	public long getLastQuestNpcObject() {
		return _questNpcObject;
	}

	public void setLastQuestNpcObject(long npcId) {
		_questNpcObject = npcId;
	}

	/**
	 * 根据任务名查询任务状态.<BR>
	 * <BR>
	 * 
	 * @param quest
	 *            The name of the quest
	 */
	public QuestState getQuestState(String quest) {
		return _quests.get(quest);
	}

	/**
	 * 给玩家加入一个任务状态.<BR>
	 * <BR>
	 * 
	 * @param qs
	 *            The QuestState to add to _quest
	 */
	public void setQuestState(QuestState qs) {
		_quests.put(qs.getQuestName(), qs);
	}

	/**
	 * 根据任务名删除一个任务状态
	 * 
	 * @param quest
	 *            The name of the quest
	 */
	public void delQuestState(String quest) {
		_quests.remove(quest);
	}

	/**
	 * 从表中返回包含的所有已经 开始(State.STARTED) 的任务.<BR>
	 * <BR>
	 */
	public Quest[] getAllActiveQuests() {
		FastList<Quest> quests = new FastList<Quest>();

		for (QuestState qs : _quests.values()) {
			if (qs == null)
				continue;

			int questId = qs.getQuest().getQuestIntId();
			if ((questId > 19999) || (questId < 1))
				continue;

			if (!qs.isStarted() && !Config.DEVELOPER)
				continue;

			quests.add(qs.getQuest());
		}

		return quests.toArray(new Quest[quests.size()]);
	}

	/**
	 * Return a table containing all QuestState to modify after a L2Attackable killing.<BR>
	 * <BR>
	 * 
	 * @param id
	 *            The Identifier of the L2Attackable attacked
	 */
	public QuestState[] getQuestsForAttacks(L2Npc npc) {
		return getQuestByNpcWithEvent(npc.getTemplate(), Quest.QuestEventType.ON_ATTACK);
	}

	/**
	 * Return a table containing all QuestState to modify after a L2Attackable killing.<BR>
	 * <BR>
	 * 
	 * @param id
	 *            The Identifier of the L2Attackable killed
	 */
	public QuestState[] getQuestsForKills(L2Npc npc) {
		return getQuestByNpcWithEvent(npc.getTemplate(), Quest.QuestEventType.ON_KILL);
	}

	/**
	 * 和某个NPC对话获取所有的自己的任务状态<BR>
	 * <BR>
	 * 
	 * @param npcId
	 *            npc模板ID
	 */
	public QuestState[] getQuestsForTalk(int npcId) {
		return getQuestByNpcWithEvent(NpcTemplateTable.getInstance().getTemplate(npcId), Quest.QuestEventType.ON_TALK);
	}

	private QuestState[] getQuestByNpcWithEvent(NpcTemplate npctpl, QuestEventType type) {
		// Create a QuestState table that will contain all QuestState to modify
		QuestState[] states = null;
		// Go through the QuestState of the L2PcInstance quests
		QuestState state;
		Quest[] quests = npctpl.getEventQuests(type);
		if (quests != null) {
			for (Quest quest : quests) {
				// Check if the Identifier of the L2Attackable attck is needed
				// for
				// the current quest
				state = getQuestState(quest.getName());
				if (state != null) {
					// Copy the current L2PcInstance QuestState in the
					// QuestState
					// table
					if (states == null)
						states = new QuestState[] { getQuestState(quest.getName()) };
					else
						states = addToQuestStateArray(states, getQuestState(quest.getName()));
				}
			}
		}

		// Return a table containing all QuestState to modify
		return states;
	}

	private QuestState[] addToQuestStateArray(QuestState[] questStateArray, QuestState state) {
		int len = questStateArray.length;
		QuestState[] tmp = new QuestState[len + 1];
		for (int i = 0; i < len; i++)
			tmp[i] = questStateArray[i];
		tmp[len] = state;
		return tmp;
	}

	/**
	 * 处理任务事件
	 * 
	 * @param quest
	 * @param event
	 * @return
	 */
	public QuestState processQuestEvent(String quest, String event) {
		QuestState retval = null;
		if (event == null)
			event = "";
		if (!_quests.containsKey(quest))
			return retval;
		QuestState qs = getQuestState(quest);
		if (qs == null && event.length() == 0)
			return retval;
		if (qs == null) {
			Quest q = QuestManager.getInstance().getQuest(quest);
			if (q == null)
				return retval;
			qs = q.newQuestState(this);
		}
		if (qs != null) {
			if (getLastQuestNpcObject() > 0) {
				L2Object object = FuzeWorld.getInstance().findObject(getLastQuestNpcObject());
				if (object instanceof L2Npc && isInsideRadius(object, L2Npc.INTERACTION_DISTANCE)) {
					L2Npc npc = (L2Npc) object;
					QuestState[] states = getQuestsForTalk(npc.getNpcId());

					if (states != null) {
						for (QuestState state : states) {
							if ((state.getQuest().getQuestIntId() == qs.getQuest().getQuestIntId())) {
								if (qs.getQuest().notifyEvent(event, npc, this))
									showQuestWindow(quest, State.getStateName(qs.getState()));

								retval = qs;
							}
						}
						// sendPacket(new QuestList());//下发任务列表
					}
				}
			}
		}

		return retval;
	}

	/**
	 * 显示任务的界面
	 * 
	 * @param questId
	 * @param stateId
	 */
	private void showQuestWindow(String questId, String stateId) {
		String path = "data/scripts/quests/" + questId + "/" + stateId + ".htm";
		String content = HtmCache.getInstance().getHtm(path); // TODO path for
		// quests html

		if (content != null) {
			if (_log.isDebugEnabled())
				_log.debug("Showing quest window for quest " + questId + " state " + stateId + " html path: " + path, Config.SERVER_ID, "显示任务的界面");

			// NpcHtmlMessage npcReply = new NpcHtmlMessage(5);
			// npcReply.setHtml(content);
			// sendPacket(npcReply);
		}

		sendPacket(ActionFailed.STATIC_PACKET);
	}

	/**
	 * Add QuestState instance that is to be notified of L2PcInstance's death.<BR>
	 * <BR>
	 * 
	 * @param qs
	 *            The QuestState that subscribe to this event
	 */
	public void addNotifyQuestOfDeath(QuestState qs) {
		if (qs == null || _NotifyQuestOfDeathList.contains(qs))
			return;

		_NotifyQuestOfDeathList.add(qs);
	}

	/**
	 * Remove QuestState instance that is to be notified of L2PcInstance's death.<BR>
	 * <BR>
	 * 
	 * @param qs
	 *            The QuestState that subscribe to this event
	 */
	public void removeNotifyQuestOfDeath(QuestState qs) {
		if (qs == null || !_NotifyQuestOfDeathList.contains(qs))
			return;

		_NotifyQuestOfDeathList.remove(qs);
	}

	/**
	 * Return a list of QuestStates which registered for notify of death of this L2PcInstance.<BR>
	 * <BR>
	 */
	public final List<QuestState> getNotifyQuestOfDeath() {
		if (_NotifyQuestOfDeathList == null)
			_NotifyQuestOfDeathList = new FastList<QuestState>();

		return _NotifyQuestOfDeathList;
	}

	/*------------------------------快捷图标控制部分---------------------------------*/

	/**
	 * 返回所有的快捷方式对象.<BR>
	 * <BR>
	 */
	public Collection<L2ShortCut> getAllShortCuts() {
		return _shortCuts.getAllShortCuts().values();
	}

	/**
	 * Return the L2ShortCut of the L2PcInstance corresponding to the position(page-slot).<BR>
	 * <BR>
	 * 
	 * @param slot
	 *            The slot in wich the shortCuts is equiped
	 */
	public L2ShortCut getShortCut(int slot) {
		return _shortCuts.getShortCut(slot);
	}

	/**
	 * 注册一个快捷方式<BR>
	 * <BR>
	 */
	public void registerShortCut(L2ShortCut shortcut) {
		_shortCuts.registerShortCut(shortcut);
	}

	/**
	 * 注册一个掉落过滤选择器
	 * 
	 * @param dropItemSelect
	 */
	public void registDropItemSelectInterface(DropItemSelectInterface dropItemSelect) {
		if (_inventory != null) {
			_inventory.registDropItemSelectInterface(dropItemSelect);
		}
	}

	/**
	 * 移除掉落过滤去
	 */
	public void removeDropItemSelectInterface() {
		if (_inventory != null) {
			_inventory.removeDropItemSelectInterface();
		}
	}

	/**
	 * 删除一个槽位上的快捷方式
	 * 
	 * @param slot
	 */
	public void deleteShortCut(int slot, boolean confirm) {
		_shortCuts.deleteShortCut(slot, confirm);
	}

	/*------------------------------PK竞技部分---------------------------------*/

	/**
	 * 设置对象的PVP状态.<BR>
	 * <BR>
	 */
	public void setPvpFlag(int pvpFlag) {
		_pvpFlag = (byte) pvpFlag;
	}

	public byte getPvpFlag() {
		return _pvpFlag;
	}

	/**
	 * 死亡 掉耐久
	 */
	private static final int REDUCEENDU_DIE = 0;

	/**
	 * 被攻击掉耐久
	 */
	public static final int REDUCEENDU_ATK = 1;

	/**
	 * 主动攻击掉耐久
	 */
	public static final int REDUCEENDU_ATKING = 2;

	/**
	 * 更新 角色耐久度 op : 0:死亡 1:被攻击
	 */
	public void updateEndurance(int op) {
		int endurance = 0;
		if (op == REDUCEENDU_DIE) {
			endurance = 100;
		} else if (op == REDUCEENDU_ATK) {
			endurance = 1;
		}

		L2ItemInstance[] items = getInventory().getAllEquipItems();
		for (L2ItemInstance item : items) {
			if (item != null) {
				item.reduceEndurance(endurance);
			}
		}

	}

	public static final float DIE_ENDURANCERADIO = 0.05f;

	public static final int ATKING_ENDURANCE = 1;

	public static final int ATKED_ENDURANCE = 1;

	/**
	 * 更新 角色耐久度 op : 0:死亡 1:被攻击
	 */
	public void updateEndurance(int op, int valus) {

		// 如果角色死亡
		if (op == REDUCEENDU_DIE) {
			L2ItemInstance[] items = getInventory().getItems();
			for (L2ItemInstance item : items) {

				if (item != null && !item.isEtcItem()) {

					item.reduceEndurance((int) (item.getEnduranceUp() * DIE_ENDURANCERADIO));

				}

			}

		}// end if (op == REDUCEENDU_DIE)
		else if (op == REDUCEENDU_ATKING) { // 主动攻击 只减少武器耐久

			L2ItemInstance it = getInventory().getPaperdollItem(Inventory.PAPERDOLL_HAND);
			if (it != null) {
				it.reduceEndurance(valus);
			}
			if (_log.isDebugEnabled()) {
				_log.debug("主动攻击 减少武器耐久:" + valus);
			}

		} else if (op == REDUCEENDU_ATK) { // 被动攻击不减少武器耐久

			L2ItemInstance[] items = getInventory().getAllEquipItems();
			for (L2ItemInstance item : items) {
				if (item != null && !item.isWeapon()) {
					item.reduceEndurance(valus);
				}
			}

			if (_log.isDebugEnabled()) {
				_log.debug("被攻击 减少装备耐久:" + valus);
			}

		}// end

	}

	/**
	 * 更新对象的PVP状态
	 */
	@Override
	public void updatePvPFlag(int value) {
		if (getPvpFlag() == value)
			return;
		setPvpFlag(value);

		// sendPacket(new UserInfo(this));
		// sendPacket(new ExBrExtraUserInfo(this));
		//
		// // If this player has a pet update the pets pvp flag as well
		// if (getPet() != null)
		// sendPacket(new RelationChanged(getPet(), getRelation(this), false));
		//
		// Collection<L2PcInstance> plrs =
		// getKnownList().getKnownPlayers().values();
		// for (L2PcInstance target : plrs) {
		// target.sendPacket(new RelationChanged(this, getRelation(this),
		// isAutoAttackable(target)));
		// if (getPet() != null)
		// target.sendPacket(new RelationChanged(getPet(), getRelation(this),
		// isAutoAttackable(target)));
		// }

	}

	/**
	 * 返回对象的pk的数量.<BR>
	 * <BR>
	 */
	public int getPkKills() {
		return _pkKills;
	}

	/**
	 * 设置对象pk的数量.<BR>
	 * <BR>
	 */
	public void setPkKills(int pkKills) {
		_pkKills = pkKills;
	}

	/**
	 * 返回这个对象被删除的时间.<BR>
	 * <BR>
	 */
	public long getDeleteTimer() {
		return _deleteTimer;
	}

	/**
	 * 设置这个对象被删除的时间<BR>
	 * <BR>
	 */
	public void setDeleteTimer(long deleteTimer) {
		_deleteTimer = deleteTimer;
	}

	/*--------------------------------善恶处理部分-------------------------------------*/

	/**
	 * 返回玩家的善恶值.<BR>
	 * <BR>
	 */
	public int getKarma() {
		return _karma;
	}

	/**
	 * 设置善恶值.<BR>
	 * <BR>
	 */
	public void setKarma(int karma) {
		_karma = karma;
	}

	/**
	 * 获得角色Pk状态
	 * 
	 * @return
	 */
	public KarmaStat getKarmaStat() {
		if (_karma >= 50)
			return KarmaStat.EVIL;
		else
			return KarmaStat.ERRANTRY;
	}

	/*--------------------------------道具装备部分-------------------------------------*/

	public void checkIfWeaponIsAllowed() {
		// Override for Gamemasters
		if (isGM())
			return;

		// Iterate through all effects currently on the character.
		for (L2Effect currenteffect : getAllEffects()) {
			L2Skill effectSkill = currenteffect.getSkill();

			// Ignore all buff skills that are party related (ie. songs, dances)
			// while still remaining weapon dependant on cast though.
			if (!effectSkill.isOffensive() && !(effectSkill.getTargetType() == SkillTargetType.TARGET_PARTY && effectSkill.getSkillType() == L2SkillType.BUFF)) {
				// Check to rest to assure current effect meets weapon
				// requirements.
				if (!effectSkill.getWeaponDependancy(this)) {
					sendMessage(effectSkill.getName() + " cannot be used with this weapon.");
					if (_log.isDebugEnabled())
						_log.debug("   | Skill " + effectSkill.getName() + " has been disabled for (" + getName() + "); Reason: Incompatible Weapon Type.", Config.SERVER_ID, getName());
					currenteffect.exit();
				}
			}

			continue;
		}
	}

	/**
	 * 装备 或 卸下一个物品 当使用这个函数时，如果装备已装备了那么将会被卸下。 UseItem里调用
	 * 
	 * @param item
	 * @param abortAttack
	 */
	public void useEquippableItem(L2ItemInstance item, boolean abortAttack) {
		// Equip or unEquip
		L2ItemInstance[] items = null;
		// 是否装备
		final boolean isEquiped = item.isEquipped();
		final int oldInvLimit = getInventoryLimit();
		SystemMessage sm = null;
		// 获得双手武器装备
		L2ItemInstance old = getInventory().getPaperdollItem(Inventory.PAPERDOLL_HAND);
		// if (old == null)
		// //没有双手武器 获得右手装备
		// old = getInventory().getPaperdollItem(Inventory.PAPERDOLL_RHAND);

		// 已经装备了
		if (isEquiped) {

			sm = new SystemMessage(SystemMessageId.S1_DISARMED);
			sm.addItemName(item);
			sendPacket(sm);

			int slot = getInventory().getSlotFromItem(item);
			// we cant unequip talisman by body slot
			// 不能通过一个装备孔 卸下一个附身符
			if (slot == L2Item.SLOT_DECO)
				items = getInventory().unEquipItemInSlotAndRecord(item.getLocationSlot());
			else
				items = getInventory().unEquipItemInBodySlotAndRecord(slot);
		}
		// 没有装备
		else {
			int tempBodyPart = item.getItem().getBodyPart();
			L2ItemInstance tempItem = getInventory().getPaperdollItemByL2ItemId(tempBodyPart);

			// check if the item replaces a wear-item
			// 这个物品 是不是试穿物品
			if (tempItem != null && tempItem.isWear()) {
				// dont allow an item to replace a wear-item
				return;
			} else if (tempBodyPart == L2Item.SLOT_HAND) {
				// this may not remove left OR right hand equipment
				tempItem = getInventory().getPaperdollItem(Inventory.PAPERDOLL_HAND);
				if (tempItem != null && tempItem.isWear())
					return;
			}

			if (item.getEnchantLevel() > 0) {
				sm = new SystemMessage(SystemMessageId.S1_S2_EQUIPPED);
				sm.addNumber(item.getEnchantLevel());
				sm.addItemName(item);
			} else {
				sm = new SystemMessage(SystemMessageId.S1_EQUIPPED);
				sm.addItemName(item);
			}
			sendPacket(sm);

			items = getInventory().equipItemAndRecord(item);

		}
		sm = null;

		/**
		 * // remove effects which doesn't match weapon type (but not party buffs) if (item.getItem().getType2() == L2Item.TYPE2_WEAPON) checkIfWeaponIsAllowed();
		 **/

		// 广播玩家信息
		broadcastUserInfo();

		// 更新背包
		InventoryUpdate iu = new InventoryUpdate();
		iu.addItems(Arrays.asList(items));
		sendPacket(iu);
		//
		// if (abortAttack)
		// abortAttack();
		//
		// if (getInventoryLimit() != oldInvLimit)
		// sendPacket(new ExStorageMaxCount(this));
	}

	/**
	 * 设置玩家最初的武器(使用在没有武器装备的时候).<BR>
	 * <BR>
	 * 
	 * @param weaponItem
	 *            The fists L2Weapon to set to the L2PcInstance
	 */
	public void setFistsWeaponItem(L2Weapon weaponItem) {
		_fistsWeaponItem = weaponItem;
	}

	/**
	 * Return the fists weapon of the L2PcInstance (used when no weapon is equiped).<BR>
	 * <BR>
	 */
	public L2Weapon getFistsWeaponItem() {
		return _fistsWeaponItem;
	}

	/**
	 * 根据玩家的职业返回最初的武器装备(used when no weapon is equiped).<BR>
	 * <BR>
	 */
	public L2Weapon findFistsWeaponItem(int classId) {
		L2Weapon weaponItem = null;
		if ((classId >= 0x00) && (classId <= 0x09)) {
			// human fighter fists
			L2Item temp = ItemTable.getInstance().getTemplate(246);
			weaponItem = (L2Weapon) temp;
		} else if ((classId >= 0x0a) && (classId <= 0x11)) {
			// human mage fists
			L2Item temp = ItemTable.getInstance().getTemplate(251);
			weaponItem = (L2Weapon) temp;
		} else if ((classId >= 0x12) && (classId <= 0x18)) {
			// elven fighter fists
			L2Item temp = ItemTable.getInstance().getTemplate(244);
			weaponItem = (L2Weapon) temp;
		} else if ((classId >= 0x19) && (classId <= 0x1e)) {
			// elven mage fists
			L2Item temp = ItemTable.getInstance().getTemplate(249);
			weaponItem = (L2Weapon) temp;
		} else if ((classId >= 0x1f) && (classId <= 0x25)) {
			// dark elven fighter fists
			L2Item temp = ItemTable.getInstance().getTemplate(245);
			weaponItem = (L2Weapon) temp;
		} else if ((classId >= 0x26) && (classId <= 0x2b)) {
			// dark elven mage fists
			L2Item temp = ItemTable.getInstance().getTemplate(250);
			weaponItem = (L2Weapon) temp;
		} else if ((classId >= 0x2c) && (classId <= 0x30)) {
			// orc fighter fists
			L2Item temp = ItemTable.getInstance().getTemplate(248);
			weaponItem = (L2Weapon) temp;
		} else if ((classId >= 0x31) && (classId <= 0x34)) {
			// orc mage fists
			L2Item temp = ItemTable.getInstance().getTemplate(252);
			weaponItem = (L2Weapon) temp;
		} else if ((classId >= 0x35) && (classId <= 0x39)) {
			// dwarven fists
			L2Item temp = ItemTable.getInstance().getTemplate(247);
			weaponItem = (L2Weapon) temp;
		}

		return weaponItem;
	}

	/**
	 * 重新给那些不保存在数据库的技能，如：帮会技能等<BR>
	 * <BR>
	 */
	public void regiveTemporarySkills() {
		// Do not call this on enterworld or char load

		// Add clan skills
		if (getClan() != null) {
			L2Clan clan = getClan();
			if (clan.getReputationScore() >= 0) {
				L2Skill[] skills = getClan().getAllSkills();
				for (L2Skill sk : skills) {
					// if (sk.getMinPledgeClass() <= getPledgeClass())
					addSkill(sk, false);
				}
			}
		}

		// Reload passive skills from armors / jewels / weapons
		getInventory().reloadEquippedItems();

	}

	/**
	 * 返回玩家的经验值
	 * 
	 * @return
	 */
	public int getExp() {
		return getStat().getExp();
	}

	/** Set the Experience value of the L2PcInstance. */
	public void setExp(int exp) {
		if (exp < 0)
			exp = 0;
		getStat().setExp(exp);
	}

	/**
	 * 返回玩家的帮派ID
	 * 
	 * @return
	 */
	public long getClanId() {
		return _clanId;
	}

	public long getClanJoinExpiryTime() {
		return _clanJoinExpiryTime;
	}

	public void setClanJoinExpiryTime(long time) {
		_clanJoinExpiryTime = time;
	}

	public long getClanCreateExpiryTime() {
		return _clanCreateExpiryTime;
	}

	public void setClanCreateExpiryTime(long time) {
		_clanCreateExpiryTime = time;
	}

	public void setOnlineTime(long time) {
		_onlineTime = time;
		_onlineBeginTime = System.currentTimeMillis();
	}

	public long getOnlineTime() {
		return _onlineTime;
	}

	public long getOnlineBeginTime() {
		return _onlineBeginTime;
	}

	/**
	 * 返回玩家的背包对象.<BR>
	 * <BR>
	 */
	@Override
	public PcInventory getInventory() {
		return _inventory;
	}

	/**
	 * Delete a ShortCut of the L2PcInstance _shortCuts.<BR>
	 * <BR>
	 */
	public void removeItemFromShortCut(long objectId) {
		_shortCuts.deleteShortCutByObjectId(objectId);
	}

	public String getAutoPK() {
		return _autoPK;
	}

	public void setAutoPK(String autoPk) {
		_autoPK = autoPk;
	}

	/**
	 * 返回玩家的仓库对象.<BR>
	 * <BR>
	 */
	public PcWarehouse getWarehouse() {
		if (_warehouse == null) {
			_warehouse = new PcWarehouse(this);
			_warehouse.restore();
			// _warehouse.setMaxCurrentSoltNums(ItemsDb.restorePcWarehouseContainer(this._objectId));
		}
		return _warehouse;
	}

	/**
	 * Free memory used by Warehouse
	 */
	public void clearWarehouse() {
		_warehouse.deleteMe();
	}

	/**
	 * Return the PcFreight object of the L2PcInstance.<BR>
	 * <BR>
	 */
	public PcFreight getFreight() {
		if (_freight == null) {
			_freight = new PcFreight(this);
			// _freight.restore();
		}
		return _freight;
	}

	/**
	 * Free memory used by Freight
	 */
	public void clearFreight() {
		if (_freight != null)
			_freight.deleteMe();

		_freight = null;
	}

	/**
	 * Return deposited PcFreight object for the objectId or create new if not exist
	 */
	public PcFreight getDepositedFreight(int objectId) {
		if (_depositedFreight == null)
			_depositedFreight = new FastList<PcFreight>();
		else {
			for (PcFreight freight : _depositedFreight) {
				if (freight != null && freight.getOwnerId() == objectId)
					return freight;
			}
		}

		PcFreight freight = new PcFreight(null);
		freight.doQuickRestore(objectId);
		_depositedFreight.add(freight);
		return freight;
	}

	/**
	 * Clear memory used by deposited freight
	 */
	public void clearDepositedFreight() {
		if (_depositedFreight == null)
			return;

		for (PcFreight freight : _depositedFreight) {
			if (freight != null) {
				try {
					freight.deleteMe();
				} catch (Exception e) {
				}
			}
		}
		_depositedFreight.clear();
		_depositedFreight = null;
	}

	/**
	 * 角色身上的银文是否足够
	 * 
	 * @param process
	 *            : 当涉及的操作 需要 自动扣银票时 这个参数 不应该为空 或者null 会涉及银文 和 银票转换的操作， 可以查看经济系统
	 * @param needMoney
	 * @return
	 */
	public boolean hasEnoughSilverMoney(String process, int needMoney) {
		if (_inventory != null) {
			return _inventory.hasEnoughSilverMoney(process, this, needMoney);
		}

		return false;
	}

	/**
	 * 返回玩家银子数.<BR>
	 * <BR>
	 */
	public int getMoneySilver() {
		return _inventory.getMoneySilver();
	}

	/**
	 * 获得积分数
	 * 
	 * @return
	 */
	public int getMoneyPoint() {
		return _inventory.getMoneyPoint();
	}

	/**
	 * 返回玩家获得银票数.<BR>
	 * <BR>
	 */
	public int getMoneyNote() {
		return _inventory.getMoneyNote();
	}

	/**
	 * 获得玩家身上的元宝数
	 * 
	 * @return
	 */
	public int getMoneyYuanBao() {
		return _inventory.getMoneyYuanBao();
	}

	/**
	 * 增加玩家身上的积分
	 * 
	 * @param process
	 * @param count
	 * @param reference
	 * @param sendMessage
	 */
	public void addMoneyPoint(String process, int count, L2Object reference, boolean sendMessage) {

		if (sendMessage) {
			SystemMessage sm = new SystemMessage(SystemMessageId.EARNED_S2_S1_S);
			sm.addItemName(PcInventory.MONEY_POINT_ID);
			sm.addItemNumber(count);
			sendPacket(sm);
		}

		if (count > 0) {
			_inventory.addMoneyPoint(process, count, this, reference);
			_logSb.setLength(0);
			_logSb.append("增加积分:").append(process).append(getName()).append("(").append(getObjectId()).append(")").append("增加积分:").append(count);
			_log.info(_logSb.toString(), getObjectId(), getName());
		}

	}

	/**
	 * 减少玩家身上的积分
	 * 
	 * @param process
	 * @param count
	 * @param reference
	 * @param sendMessage
	 * @return
	 */
	public boolean reduceMoneyPoint(String process, int count, L2Object reference, boolean sendMessage) {
		if (count > getMoneyPoint()) {
			if (sendMessage) // 改成积分系统消息 TODO:
				sendPacket(new SystemMessage(SystemMessageId.YOU_NOT_ENOUGH_ADENA));
			return false;
		}

		process = process + ",";

		if (count > 0) {
			L2ItemInstance moneyItem = _inventory.getMoneyPointInstance();

			_inventory.reduceMoneyPoint(process, count, this, reference);

			_logSb.setLength(0);
			_logSb.append("减少积分:").append(process).append(getName()).append("(").append(getObjectId()).append(")").append("减少积分数:").append(count);
			_log.info(_logSb.toString(), getObjectId(), getName());

			InventoryUpdate iu = new InventoryUpdate();
			iu.addItem(moneyItem);
			sendPacket(iu);

			if (sendMessage) {
				SystemMessage sm = new SystemMessage(SystemMessageId.S2_S1_DISAPPEARED);
				sm.addItemName(PcInventory.MONEY_POINT_ID);
				sm.addItemNumber(count);
				sendPacket(sm);
			}
		}

		return true;
	}

	/**
	 * 增加游戏银文
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param count
	 *            : int Quantity of adena to be added
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 */
	public void addMoneySilver(String process, int count, L2Object reference, boolean sendMessage) {
		if (sendMessage) {
			SystemMessage sm = new SystemMessage(SystemMessageId.EARNED_ADENA);
			sm.addItemNumber(count);
			sendPacket(sm);
		}

		if (count > 0) {
			_inventory.addMoneySilver(process, count, this, reference);

			_logSb.setLength(0);
			_logSb.append("增加银文:").append(process).append(getName()).append("(").append(getObjectId()).append(")").append("增加银文:").append(count);
			_log.info(_logSb.toString(), getObjectId(), getName());
		}
	}

	/**
	 * 减少游戏银文
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param count
	 *            : long Quantity of adena to be reduced
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 * @return boolean informing if the action was successfull
	 */
	public boolean reduceMoneySilver(String process, int count, L2Object reference, boolean sendMessage) {
		if (!OPSTATE.isInThis(process) && count > getMoneySilver()) {
			if (sendMessage)
				sendPacket(new SystemMessage(SystemMessageId.YOU_NOT_ENOUGH_ADENA));
			return false;
		}

		if (_log.isDebugEnabled()) {
			_log.debug("减少角色银文:" + count);
		}

		process = process + ",";

		if (count > 0) {
			L2ItemInstance moneyItem = _inventory.getMoneySilverInstance();
			int silverNums = getMoneySilver();

			if (moneyItem != null) {
				_logSb.setLength(0);
				_logSb.append("减少银文:").append(process).append(getName()).append("(").append(getObjectId()).append(")").append("减少银文:").append(silverNums > count ? count : silverNums);
				_log.info(_logSb.toString(), getObjectId(), getName());
			}

			_inventory.reduceMoneySilver(process, count, this, reference);

			InventoryUpdate iu = new InventoryUpdate();
			iu.addItem(moneyItem);
			sendPacket(iu);

			if (sendMessage && silverNums > 0) {
				SystemMessage sm = new SystemMessage(SystemMessageId.DISAPPEARED_ADENA);
				sm.addItemNumber((silverNums > count ? count : silverNums));
				sendPacket(sm);
			}
		}

		return true;
	}

	/**
	 * 增加游戏银票
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param count
	 *            : int Quantity of ancient adena to be added
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 */
	public void addMoneyNote(String process, int count, L2Object reference, boolean sendMessage) {
		if (sendMessage) {
			SystemMessage sm = new SystemMessage(SystemMessageId.EARNED_S2_S1_S);
			sm.addItemName(PcInventory.MONEY_NOTE_ID);
			sm.addItemNumber(count);
			sendPacket(sm);
		}

		if (count > 0) {
			_inventory.addMoneyNote(process, count, this, reference);

			_logSb.setLength(0);
			_logSb.append("增加银票:").append(process).append(getName()).append("(").append(getObjectId()).append(")").append("增加银票:").append(count);
			_log.info(_logSb.toString(), getObjectId(), getName());
		}
	}

	/**
	 * 增加元宝
	 * 
	 * @param process
	 * @param count
	 * @param reference
	 * @param sendMessage
	 */
	public void addMoneyYuanBao(String process, int count, L2Object reference, boolean sendMessage) {
		if (sendMessage) {
			SystemMessage sm = new SystemMessage(SystemMessageId.EARNED_S2_S1_S);
			sm.addItemName(PcInventory.MONEY_YAUNBAO_ID);
			sm.addItemNumber(count);
			sendPacket(sm);
		}

		if (count > 0) {
			_inventory.addMoneyYuanBao(process, count, this, reference);

			_logSb.setLength(0);
			_logSb.append("增加元宝:").append(process).append(getName()).append("(").append(getObjectId()).append(")").append("增加元宝:").append(count);
			_log.info(_logSb.toString(), getObjectId(), getName());
		}

	}

	/**
	 * 减少元宝数
	 * 
	 * @param process
	 * @param count
	 * @param reference
	 * @param sendMessage
	 * @return
	 */
	public boolean reduceMoneyYuanBao(String process, int count, L2Object reference, boolean sendMessage) {
		if (count > getMoneyYuanBao()) {
			if (sendMessage)
				sendPacket(new SystemMessage(SystemMessageId.YOU_NOT_ENOUGH_YUANBAO));

			return false;
		}

		process = process + ",";

		if (count > 0) {
			L2ItemInstance moneyItem = _inventory.getMoneyYubaoInstance();
			_inventory.reduceMoneyYuanBao(process, count, this, reference);

			_logSb.setLength(0);
			_logSb.append("减少元宝:").append(process).append(getName()).append("(").append(getObjectId()).append(")").append("减少元宝:").append(count);
			_log.info(_logSb.toString(), getObjectId(), getName());

			InventoryUpdate iu = new InventoryUpdate();
			iu.addItem(moneyItem);
			sendPacket(iu);

			if (sendMessage) {
				SystemMessage sm = new SystemMessage(SystemMessageId.S2_S1_DISAPPEARED);
				sm.addItemName(PcInventory.MONEY_YAUNBAO_ID);
				sm.addItemNumber(count);
				sendPacket(sm);
			}
		}

		return true;

	}

	/**
	 * 减少游戏银票
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param count
	 *            : long Quantity of ancient adena to be reduced
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 * @return boolean informing if the action was successfull
	 */
	public boolean reduceMoneyNote(String process, int count, L2Object reference, boolean sendMessage) {
		if (count > getMoneyNote()) {
			if (sendMessage)
				sendPacket(new SystemMessage(SystemMessageId.YOU_NOT_ENOUGH_ADENA));

			return false;
		}

		process = process + ",";

		if (count > 0) {
			L2ItemInstance moneyItem = _inventory.getMoneyNoteInstance();
			_inventory.reduceMoneyNote(process, count, this, reference);

			_logSb.setLength(0);
			_logSb.append("减少银票:").append(process).append(getName()).append("(").append(getObjectId()).append(")").append("减少积分数:").append(count);
			_log.info(_logSb.toString(), getObjectId(), getName());

			InventoryUpdate iu = new InventoryUpdate();
			iu.addItem(moneyItem);
			sendPacket(iu);

			if (sendMessage) {
				SystemMessage sm = new SystemMessage(SystemMessageId.S2_S1_DISAPPEARED);
				sm.addItemName(PcInventory.MONEY_NOTE_ID);
				sm.addItemNumber(count);
				sendPacket(sm);
			}
		}

		return true;
	}

	/**
	 * 加入道具到玩家的背包，并且发送背包更新的包给客户端.
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param item
	 *            : L2ItemInstance to be added
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 */
	public L2ItemInstance addItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage) {
		if (item.getCount() > 0) {

			if (!item.isMoney() && !isGM() && !_inventory.validateCapacity(item)) {
				// 发送系统消息， 背包已满
//				sendPacket(new SystemMessage(SystemMessageId.INVENTORY_IS_FULL));
				sendMessage("背包已满");
				ItemTable.getInstance().destroyItem("背包满", item, this, reference);
				return null;
			}

			// 把道具加入背包
			L2ItemInstance newitem = _inventory.addItem(process, item, this, reference);

			// Sends message to client if requested
			if (newitem != null && sendMessage) {
				if (item.getCount() > 0) {
					SystemMessage sm = new SystemMessage(SystemMessageId.YOU_PICKED_UP_S1_S2);
					sm.addItemName(item);
					sm.addItemNumber(item.getCount());
					sendPacket(sm);
				} else if (item.getEnchantLevel() > 0) {
					SystemMessage sm = new SystemMessage(SystemMessageId.YOU_PICKED_UP_A_S1_S2);
					sm.addNumber(item.getEnchantLevel());
					sm.addItemName(item);
					sendPacket(sm);
				} else {
					SystemMessage sm = new SystemMessage(SystemMessageId.YOU_PICKED_UP_S1);
					sm.addItemName(item);
					sendPacket(sm);
				}

				_logSb.setLength(0);
				_logSb.append(Item_Add).append(process).append("物品名:").append(newitem.getName()).append("(").append(newitem.getObjectId()).append(")").append("数量:").append(item.getCount()).append("到");
				_logSb.append(getName()).append("(").append(getObjectId()).append(")");
				_log.info(_logSb.toString(), getObjectId(), getName());
			}

			// // 如果越过了背包的容量则把这个道具扔出去
			// if (!isGM() && !_inventory.validateCapacity(0) &&
			// newitem.isDropable())
			// dropItem("InvDrop", newitem, null, true);

			return newitem;

		}

		return null;
	}

	/**
	 * 加入道具到玩家的背包，并且发送背包更新的包给客户端.
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param itemId
	 *            : int Item Identifier of the item to be added
	 * @param count
	 *            : long Quantity of items to be added
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 */
	public L2ItemInstance addItem(String process, int itemId, int count, L2Object reference, boolean sendMessage) {
		if (count > 0) {

			if (itemId != PcInventory.MONEY_SLIVER_ID && itemId != PcInventory.MONEY_NOTE_ID && itemId != PcInventory.MONEY_YAUNBAO_ID && itemId != PcInventory.MONEY_POINT_ID && !isGM() && !_inventory.validateCapacityByItemId(itemId, count)) {
				// TODO:
				// 发送系统消息， 背包已满
//				sendPacket(new SystemMessage(SystemMessageId.INVENTORY_IS_FULL));
				sendMessage("背包已满");
				return null;
			}

			// 把道具加入背包
			L2ItemInstance createdItem = _inventory.addItem(process, itemId, count, this, reference);

			// Sends message to client if requested
			if (createdItem != null && sendMessage) {
				if (count > 0) {
					if (process.equalsIgnoreCase("Quest")) {
						SystemMessage sm = new SystemMessage(SystemMessageId.EARNED_S2_S1_S);
						sm.addItemName(itemId);
						sm.addItemNumber(count);
						sendPacket(sm);
					} else {
						SystemMessage sm = new SystemMessage(SystemMessageId.YOU_PICKED_UP_S1_S2);
						sm.addItemName(itemId);
						sm.addItemNumber(count);
						sendPacket(sm);
					}
				} else {
					if (process.equalsIgnoreCase("Quest")) {
						SystemMessage sm = new SystemMessage(SystemMessageId.EARNED_ITEM);
						sm.addItemName(itemId);
						sendPacket(sm);
					} else {
						SystemMessage sm = new SystemMessage(SystemMessageId.YOU_PICKED_UP_S1);
						sm.addItemName(itemId);
						sendPacket(sm);
					}
				}

				_logSb.setLength(0);
				_logSb.append(Item_Add).append(process).append("物品名:").append(createdItem.getName()).append("(").append(createdItem.getObjectId()).append(")").append("数量:").append(count).append("到");
				_logSb.append(getName()).append("(").append(getObjectId()).append(")");
				_log.info(_logSb.toString(), getObjectId(), getName());

			}

			// // 如果越过了背包的容量则把这个道具扔出去
			// if (!isGM() && !_inventory.validateCapacity(0) &&
			// createdItem.isDropable())
			// dropItem("InvDrop", createdItem, null, true);

			return createdItem;
		}

		return null;

	}

	/**
	 * 从玩家的背包中删除一个物品，并发包给客户端
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param item
	 *            : L2ItemInstance to be destroyed
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 * @return boolean informing if the action was successfull
	 */
	public boolean destroyItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage) {
		return destroyItem(process, item, item.getCount(), reference, sendMessage);
	}

	/**
	 * Destroy item from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance.
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param item
	 *            : L2ItemInstance to be destroyed
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 * @return boolean informing if the action was successfull
	 */
	public boolean destroyItem(String process, L2ItemInstance item, int count, L2Object reference, boolean sendMessage) {

		process = process + ",";
		item = _inventory.destroyItem(process, item, count, this, reference);

		if (item == null) {
			if (sendMessage) {
				sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));
			}
			return false;
		}

		_logSb.setLength(0);
		_logSb.append(Item_Destory).append(process).append("角色 ").append(getName()).append("(").append(getObjectId()).append(")").append("摧毁的物品: ");
		_logSb.append(item.getName()).append("(").append(item.getObjectId()).append(")").append("摧毁数量:").append(count);
		_log.info(_logSb.toString(), getObjectId(), getName());

		// Send inventory update packet
		// if (!Config.FORCE_INVENTORY_UPDATE) {
		InventoryUpdate playerIU = new InventoryUpdate();
		playerIU.addItem(item);
		sendPacket(playerIU);
		// }

		// Sends message to client if requested
		if (sendMessage) {
			SystemMessage sm = new SystemMessage(SystemMessageId.S2_S1_DISAPPEARED);
			sm.addItemName(item);
			sm.addItemNumber(count);
			sendPacket(sm);
		}

		return true;
	}

	/**
	 * Destroys item from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance.
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param objectId
	 *            : int Item Instance identifier of the item to be destroyed
	 * @param count
	 *            : int Quantity of items to be destroyed
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 * @return boolean informing if the action was successfull
	 */
	@Override
	public boolean destroyItem(String process, long objectId, int count, L2Object reference, boolean sendMessage) {
		L2ItemInstance item = _inventory.getItemByObjectId(objectId);

		if (item == null) {
			if (sendMessage) {
				sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));
			}

			return false;
		}
		return destroyItem(process, item, count, reference, sendMessage);
	}

	/**
	 * Destroys shots from inventory without logging and only occasional saving to database. Sends a Server->Client InventoryUpdate packet to the L2PcInstance.
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param objectId
	 *            : int Item Instance identifier of the item to be destroyed
	 * @param count
	 *            : int Quantity of items to be destroyed
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 * @return boolean informing if the action was successfull
	 */
	public boolean destroyItemWithoutTrace(String process, int objectId, int count, L2Object reference, boolean sendMessage) {
		L2ItemInstance item = _inventory.getItemByObjectId(objectId);

		if (item == null || item.getCount() < count) {
			if (sendMessage) {
				sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));
			}

			return false;
		}

		return destroyItem(null, item, count, reference, sendMessage);
	}

	public static String Item_Destory = "摧毁物品:";

	public static String Item_Add = "获得物品:";

	/**
	 * Destroy item from inventory by using its <B>itemId</B> and send a Server->Client InventoryUpdate packet to the L2PcInstance.
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param itemId
	 *            : int Item identifier of the item to be destroyed
	 * @param count
	 *            : int Quantity of items to be destroyed
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 * @return boolean informing if the action was successfull
	 */
	@Override
	public boolean destroyItemByItemId(String process, int itemId, int count, L2Object reference, boolean sendMessage) {
		int restCount = _inventory.getInventoryItemCount(itemId);

		// 数量不足 直接返回
		if (restCount < count) {
			if (sendMessage)
				sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));

			return false;
		}

		List<L2ItemInstance> items = _inventory.getItemsByItemId(itemId);
		InventoryUpdate playerIU = new InventoryUpdate();

		_logSb.setLength(0);
		_logSb.append(Item_Destory).append(process).append(',').append("角色 ").append(getName()).append('(').append(getObjectId()).append(')');
		// append("(").append(item.getObjectId()).append(")").append("摧毁数量:").append(count);

		restCount = count;
		for (L2ItemInstance it : items) {
			int descount = restCount - it.getCount() > 0 ? it.getCount() : restCount;
			_inventory.destroyItem(process, it, descount, this, null);
			playerIU.addItem(it);
			_logSb.append("摧毁的物品:").append(it.getName()).append('(').append(it.getObjectId()).append(')').append("摧毁数量:").append(descount);

			restCount = restCount - it.getCount();
			if (restCount <= 0) {
				break;
			}

		}

		// if (item == null || item.getCount() < count ||
		// _inventory.destroyItemByItemId(process, itemId, count, this,
		// reference) == null) {
		// if (sendMessage)
		// sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));
		//
		// return false;
		// }

		// _logSb.setLength(0);
		// _logSb.append(Item_Destory).append(process).append("角色 ").append(getName()).append("(").append(getObjectId()).append(")").append("摧毁的物品: ");
		// _logSb.append(item.getName()).append("(").append(item.getObjectId()).append(")").append("摧毁数量:").append(count);
		_log.info(_logSb.toString(), getObjectId(), getName());

		// Send inventory update packet
		// if (!Config.FORCE_INVENTORY_UPDATE) {
		// InventoryUpdate playerIU = new InventoryUpdate();
		// playerIU.addItem(item);
		sendPacket(playerIU);
		// }

		// Sends message to client if requested
		if (sendMessage) {
			SystemMessage sm = new SystemMessage(SystemMessageId.S2_S1_DISAPPEARED);
			sm.addItemName(itemId);
			sm.addItemNumber(count);
			sendPacket(sm);
		}

		return true;
	}

	/**
	 * Destroy all weared items from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance.
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 * @return boolean informing if the action was successfull
	 */
	public void destroyWearedItems(String process, L2Object reference, boolean sendMessage) {

		// Go through all Items of the inventory
		for (L2ItemInstance item : getInventory().getItems()) {
			// Check if the item is a Try On item in order to remove it
			if (item.isWear()) {
				if (item.isEquipped())
					getInventory().unEquipItemInSlotAndRecord(item.getLocationSlot());

				if (_inventory.destroyItem(process, item, this, reference) == null) {
					_log.warn("Player " + getName() + " can't destroy weared item: " + item.getName() + "[ " + item.getObjectId() + " ]", Config.SERVER_ID, item.getName());
					continue;
				}

				// Send an Unequipped Message in system window of the player for
				// each Item
				SystemMessage sm = new SystemMessage(SystemMessageId.S1_DISARMED);
				sm.addItemName(item);
				sendPacket(sm);

			}
		}

		// Send the ItemList Server->Client Packet to the player in order to
		// refresh its Inventory
		// ItemList il = new ItemList(getInventory().getItems(), true);
		// sendPacket(il);

		// Send a Server->Client packet UserInfo to this L2PcInstance and
		// CharInfo to all L2PcInstance in its _KnownPlayers
		broadcastUserInfo();

		// Sends message to client if requested
		sendMessage("Trying-on mode has ended.");

	}

	/**
	 * 转移道具到另一个道具容器中.
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param itemId
	 *            : int Item Identifier of the item to be transfered
	 * @param count
	 *            : long Quantity of items to be transfered
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @return L2ItemInstance corresponding to the new item or the updated item in inventory
	 */
	public L2ItemInstance transferItem(String process, int objectId, int count, Inventory target, L2Object reference) {
		L2ItemInstance oldItem = checkItemManipulation(objectId, count, "transfer");
		if (oldItem == null)
			return null;
		L2ItemInstance newItem = getInventory().transferItem(process, objectId, count, target, this, reference);
		if (newItem == null)
			return null;

		// Send inventory update packet
		// if (!Config.FORCE_INVENTORY_UPDATE) {
		// InventoryUpdate playerIU = new InventoryUpdate();
		// if (oldItem.getCount() > 0 && oldItem != newItem)
		// playerIU.addModifiedItem(oldItem);
		// else
		// playerIU.addRemovedItem(oldItem);
		// sendPacket(playerIU);
		// } else
		// sendPacket(new ItemList(this, false));

		// Send target update packet
		if (target instanceof PcInventory) {
			FuzePcInstance targetPlayer = ((PcInventory) target).getOwner();

			// if (!Config.FORCE_INVENTORY_UPDATE) {
			// InventoryUpdate playerIU = new InventoryUpdate();
			// if (newItem.getCount() > count)
			// playerIU.addModifiedItem(newItem);
			// else
			// playerIU.addNewItem(newItem);
			// targetPlayer.sendPacket(playerIU);
			// } else
			// targetPlayer.sendPacket(new ItemList(targetPlayer, false));
		}
		return newItem;
	}

	/**
	 * Drop item from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance.
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param item
	 *            : L2ItemInstance to be dropped
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 * @return boolean informing if the action was successfull
	 */
	public L2ItemInstance dropItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage) {

		// 如果物品 不是道具，且被绑定 或者 不能交易， 那么这个物品不能被掉落
		if (!item.isEtcItem() && (item.isBinding() || !item.isTradeable())) {
			return null;
		}

		// int oldSlot = -1;
		// if (item != null) {
		// oldSlot = item.getLocationSlot();
		// }

		process = process + ",";

		item = _inventory.dropItem(process, item, this, reference);

		// if (item != null) {
		// // 重置背包中相应槽位的标记
		// _inventory.restInventorySlot(oldSlot);
		// }

		if (item == null) {
			if (sendMessage)
				sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));

			return null;
		}

		_logSb.setLength(0);
		_logSb.append("丢弃物品:").append(process).append(item.getName()).append("(").append(item.getObjectId()).append(")").append("角色 ").append(getName()).append("(").append(getObjectId()).append(")");
		_log.info(_logSb.toString(), getObjectId(), getName());

		// item.dropMe(this, getX() + Rnd.get(50) - 25, getY() + Rnd.get(50) -
		// 25);

		// if (Config.AUTODESTROY_ITEM_AFTER > 0 &&
		// Config.DESTROY_DROPPED_PLAYER_ITEM &&
		// !Config.LIST_PROTECTED_ITEMS.contains(item.getItemId())) {
		// if ((item.isEquipable() && Config.DESTROY_EQUIPABLE_PLAYER_ITEM) ||
		// !item.isEquipable())
		// ItemsAutoDestroy.getInstance().addItem(item);
		// }

		// Send inventory update packet
		// if (!Config.FORCE_INVENTORY_UPDATE) {
		// InventoryUpdate playerIU = new InventoryUpdate();
		// playerIU.addItem(item);
		// sendPacket(playerIU);
		// } else
		// sendPacket(new ItemList(this, false));

		// Sends message to client if requested
		// if (sendMessage) {
		// SystemMessage sm = new SystemMessage(SystemMessageId.YOU_DROPPED_S1);
		// sm.addItemName(item);
		// sendPacket(sm);
		// }

		return item;
	}

	/**
	 * 这个函数 占没使用 Drop item from inventory by using its <B>objectID</B> and send a Server->Client InventoryUpdate packet to the L2PcInstance.
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param objectId
	 *            : int Item Instance identifier of the item to be dropped
	 * @param count
	 *            : long Quantity of items to be dropped
	 * @param x
	 *            : int coordinate for drop X
	 * @param y
	 *            : int coordinate for drop Y
	 * @param z
	 *            : int coordinate for drop Z
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling item or previous item in transformation
	 * @param sendMessage
	 *            : boolean Specifies whether to send message to Client about this action
	 * @return L2ItemInstance corresponding to the new item or the updated item in inventory
	 */
	public L2ItemInstance dropItem(String process, long objectId, int count, int x, int y, L2Object reference, boolean sendMessage) {
		L2ItemInstance invitem = _inventory.getItemByObjectId(objectId);

		process = process + ",";

		L2ItemInstance item = _inventory.dropItem(process, objectId, count, this, reference);

		if (item == null) {
			if (sendMessage)
				sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));

			return null;
		}

		_logSb.setLength(0);
		_logSb.append("丢弃物品:").append(item.getName()).append("(").append(item.getObjectId()).append(")").append("角色 ").append(getName()).append("(").append(getObjectId()).append(")");
		_log.info(_logSb.toString(), getObjectId(), getName());

		// 设置道具出现在世界中
		// item.dropMe(this, x, y);

		if (Config.AUTODESTROY_ITEM_AFTER > 0 && Config.DESTROY_DROPPED_PLAYER_ITEM && !Config.LIST_PROTECTED_ITEMS.contains(item.getItemId())) {
			if ((item.isEquipable() && Config.DESTROY_EQUIPABLE_PLAYER_ITEM) || !item.isEquipable())
				ItemsAutoDestroy.getInstance().addItem(item);
		}

		// 发送背包更新数据包
		if (!Config.FORCE_INVENTORY_UPDATE) {
			InventoryUpdate playerIU = new InventoryUpdate();
			playerIU.addItem(invitem);
			sendPacket(playerIU);
		} else {
			sendPacket(new ItemList(this, false));
		}

		// Sends message to client if requested
		if (sendMessage) {
			SystemMessage sm = new SystemMessage(SystemMessageId.YOU_DROPPED_S1);
			sm.addItemName(item);
			sendPacket(sm);
		}

		return item;
	}

	/**
	 * 2010.3.22 added by zjj 按背包格子的 索引值掉落物品
	 * 
	 * @param process
	 * @param slots
	 *            :背包格索引
	 * @param x
	 * @param y
	 * @param reference
	 * @param sendMessage
	 * @return
	 */
	public L2ItemInstance dropItem(String process, int slot, L2Object reference, boolean sendMessage) {
		// 获得 掉的物品， 掉落此物品
		L2ItemInstance temp = getInventory().getItemByInventorySlot(slot);
		if (temp != null) {
			return dropItem(process, temp, reference, sendMessage);
		}

		return null;
	}

	/**
	 * 通过对象ID，检测某个道具的可操作性
	 * 
	 * @param objectId
	 * @param count
	 * @param action
	 * @return
	 */
	public L2ItemInstance checkItemManipulation(long objectId, long count, String action) {
		// TODO: if we remove objects that are not visisble from the L2World,
		// we'll have to remove this check
		if (FuzeWorld.getInstance().findObject(objectId) == null) {
			_log.warn(getObjectId() + ": player tried to " + action + " item not available in FuzeWorld", getObjectId(), getName());
			return null;
		}

		L2ItemInstance item = _inventory.getItemByObjectId(objectId);

		if (item == null || item.getOwnerId() != getObjectId()) {
			_log.warn(getObjectId() + ": player tried to " + action + " item he is not owner of", getObjectId(), getName());
			return null;
		}

		if (count < 0 || (count > 1 && !item.isStackable())) {
			_log.warn(getObjectId() + ": player tried to " + action + " item with invalid count: " + count, getObjectId(), getName());
			return null;
		}

		if (count > item.getCount()) {
			_log.warn(getObjectId() + ": player tried to " + action + " more items than he owns", getObjectId(), getName());
			return null;
		}

		// Pet is summoned and not the item that summoned the pet AND not the
		// buggle from strider you're mounting
		if (getPet() != null && getPet().getControlItemId() == objectId || getMountObjectID() == objectId) {
			if (_log.isDebugEnabled())
				_log.debug(getObjectId() + " player tried to " + action + " item controling pet", getObjectId(), getName());

			return null;
		}

		// 不能扔掉或交易试穿道具
		if (item.isWear()) {
			return null;
		}

		return item;
	}

	/**
	 * 检查道具的操作可行性 Performs following tests:<br>
	 * <li>Inventory contains item <li>Item owner id == this.owner id <li>It isnt pet control item while mounting pet or pet summoned <li>It isnt active enchant item <li>It isnt wear item <br>
	 * 
	 * @param objectId
	 *            : item object id
	 * @param action
	 *            : just for login porpouse
	 * @return
	 */
	public boolean validateItemManipulation(long objectId, String action) {
		L2ItemInstance item = getInventory().getItemByObjectId(objectId);

		if (item == null || item.getOwnerId() != getObjectId()) {
			_log.warn(getObjectId() + ": player tried to " + action + " item he is not owner of", getObjectId(), getName());
			return false;
		}

		// Pet is summoned and not the item that summoned the pet AND not the
		// buggle from strider you're mounting
		if (getPet() != null && getPet().getControlItemId() == objectId || getMountObjectID() == objectId) {
			if (_log.isDebugEnabled())
				_log.debug(getObjectId() + ": player tried to " + action + " item controling pet", getObjectId(), getName());

			return false;
		}

		if (item.isWear()) {
			// cannot drop/trade wear-items
			return false;
		}

		return true;
	}

	/**
	 * 是否处于出生保护
	 * 
	 * @return
	 */
	public boolean isSpawnProtected() {
		return _protectEndTime > GameTimeController.getGameTicks();
	}

	/**
	 * 设置玩家的保护时间，当玩家跳转场景的时候设置玩家一定时间不受伤害
	 */
	public void setProtection(boolean protect) {
		if (_log.isDebugEnabled())
			_log.debug(getName() + ": Protection " + (protect ? "ON " + (GameTimeController.getGameTicks() + Config.PLAYER_SPAWN_PROTECTION * GameTimeController.TICKS_PER_SECOND) : "OFF") + " (currently " + GameTimeController.getGameTicks() + ")", Config.SERVER_ID, getName());

		_protectEndTime = protect ? GameTimeController.getGameTicks() + Config.PLAYER_SPAWN_PROTECTION * GameTimeController.TICKS_PER_SECOND : 0;
	}

	/**
	 * Get the client owner of this char.<BR>
	 * <BR>
	 */
	public L2GameClient getClient() {
		return _client;
	}

	public void setClient(L2GameClient client) {
		_client = client;
	}

	/**
	 * 关闭激活的客户端的连接.<BR>
	 * <BR>
	 */
	public void closeNetConnection() {
		L2GameClient client = _client;
		if (client != null) {
			if (!client.isDetached()) {// 如果没有分离，关闭的网络连接，有底层正常断网事件触发写磁盘逻辑
				if (!client.getConnection().isClosed()) {
					client.close(LeaveWorld.LEAVEWORLD);
				}
			} else {// 直接通知断网，用在客户端强退的情况下
				client.onDisconnection();
			}
		}
	}

	/**
	 * 登出游戏处理.<BR>
	 * <BR>
	 * 
	 * @param charList
	 *            TODO
	 */
	public void logout(boolean charList) {
		if (!_isOnline)
			return;
		deleteMe();
		if (charList) {
			getClient().RegetCharList();
		} else
			closeNetConnection();
	}

	/**
	 * 获得当前放在地上的技能的坐标
	 * 
	 * @return
	 */
	public Point2D getCurrentSkillWorldPosition() {
		return _currentSkillWorldPosition;
	}

	/**
	 * 设置当前放在地上的技能坐标
	 * 
	 * @param worldPosition
	 */
	public void setCurrentSkillWorldPosition(Point2D worldPosition) {
		_currentSkillWorldPosition = worldPosition;
	}

	/**
	 * 此对象攻击一个目标的逻辑
	 * 
	 * @see labox.innovation.gameserver.model.actor.L2Character#doAttack(labox.innovation.gameserver.model.actor.L2Character)
	 */
	@Override
	protected void doAttack(L2Character target) {
		if (getAppearance().getInvisible()) {
			L2Effect eInvisible = getFirstEffect(L2EffectType.HIDE);
			if (eInvisible != null)
				eInvisible.exit();
		}

		// Checking if target has moved to peace zone
		if (target.isInsidePeaceZone(this)) {// 如果目标是在安全区域
			getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
			sendPacket(new SystemMessage(SystemMessageId.TARGET_IN_PEACEZONE));
			return;
		}

		super.doAttack(target);
		// updateEndurance(REDUCEENDU_ATK);
//		updateEndurance(REDUCEENDU_ATKING, ATKING_ENDURANCE);

	}

	/**
	 * 此对象施法一个技能的逻辑
	 * 
	 * @see labox.innovation.gameserver.model.actor.L2Character#doCast(labox.innovation.gameserver.model.L2Skill)
	 */
	@Override
	public void doCast(L2Skill skill) {
		if (getAppearance().getInvisible()) {
			L2Effect eInvisible = getFirstEffect(L2EffectType.HIDE);
			if (eInvisible != null)
				eInvisible.exit();
		}
		super.doCast(skill);
		updateEndurance(REDUCEENDU_ATKING, ATKING_ENDURANCE);
	}

	/**
	 * 管理交互当一个玩家点击这个玩家对象.<BR>
	 * <BR>
	 * <B><U> Actions on first click on the L2PcInstance (Select it)</U> :</B><BR>
	 * <BR>
	 * <li>Set the target of the player</li> <li>Send a Server->Client packet MyTargetSelected to the player (display the select window)</li><BR>
	 * <BR>
	 * <B><U> Actions on second click on the L2PcInstance (Follow it/Attack it/Intercat with it)</U> :</B><BR>
	 * <BR>
	 * <li>Send a Server->Client packet MyTargetSelected to the player (display the select window)</li> <li>If this L2PcInstance has a Private Store, notify the player AI with AI_INTENTION_INTERACT</li> <li>If this L2PcInstance is autoAttackable, notify the player AI with AI_INTENTION_ATTACK</li><BR>
	 * <BR>
	 * <li>If this L2PcInstance is NOT autoAttackable, notify the player AI with AI_INTENTION_FOLLOW</li><BR>
	 * <BR>
	 * <B><U> Example of use </U> :</B><BR>
	 * <BR>
	 * <li>Client packet : Action, AttackRequest</li><BR>
	 * <BR>
	 * 
	 * @param player
	 *            The player that start an action on this L2PcInstance
	 */

	@Override
	public void onAction(FuzePcInstance player) {

		// Check if the L2PcInstance is confused
		if (player.isOutOfControl()) {
			// Send a Server->Client packet ActionFailed to the player
			player.sendPacket(ActionFailed.STATIC_PACKET);
			return;
		}

		// Aggression target lock effect
		if (player.isLockedTarget() && player.getLockedTarget() != this) {
			player.sendPacket(new SystemMessage(SystemMessageId.FAILED_CHANGE_TARGET));
			player.sendPacket(ActionFailed.STATIC_PACKET);
			return;
		}

		// 如果调查者的目标不在此玩家身上，设置目标为此玩家
		if (player.getTarget() != this) {
			// Set the target of the player
			player.setTarget(this);
		}

		if (isAutoAttackable(player)) {
			// 检查是否玩家有自动攻击能力
			// if (GeoData.getInstance().canSeeTarget(player, this))
			// {//如果可以看到此玩家则开始攻击AI
			player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);
			// }
		} else {
			player.sendPacket(ActionFailed.STATIC_PACKET);
		}

	}

	/**
	 * GM调用的方法，GM查看用户的信息时使用
	 */
	@Override
	public void onActionShift(L2GameClient client) {
		FuzePcInstance player = client.getActiveChar();
		if (player == null)
			return;

		if (player.isGM()) {
			// Check if the gm already target this l2pcinstance
			if (player.getTarget() != this) {
				// Set the target of the L2PcInstance player
				player.setTarget(this);
			}

			IAdminCommandHandler ach = AdminCommandHandler.getInstance().getAdminCommandHandler("admin_character_info");
			if (ach != null)
				ach.useAdminCommand("admin_character_info " + getName(), player);
		}
		player.sendPacket(ActionFailed.STATIC_PACKET);
	}

	// /**
	// * Returns true if mp update should be done, false if not
	// *
	// * @return boolean
	// */
	// private boolean needMpUpdate(int barPixels) {
	// double currentMp = getCurrentMp();
	//
	// if (currentMp <= 1.0 || getMaxMp() < barPixels)
	// return true;
	//
	// if (currentMp <= _mpUpdateDecCheck || currentMp >= _mpUpdateIncCheck) {
	// if (currentMp == getMaxMp()) {
	// _mpUpdateIncCheck = currentMp + 1;
	// _mpUpdateDecCheck = currentMp - _mpUpdateInterval;
	// } else {
	// double doubleMulti = currentMp / _mpUpdateInterval;
	// int intMulti = (int) doubleMulti;
	//
	// _mpUpdateDecCheck = _mpUpdateInterval * (doubleMulti < intMulti ?
	// intMulti-- : intMulti);
	// _mpUpdateIncCheck = _mpUpdateDecCheck + _mpUpdateInterval;
	// }
	//
	// return true;
	// }
	//
	// return false;
	// }

	/**
	 * 广播当前玩家的HP,MP,CP的状态。玩家实例中此方法覆盖了L2Character中的此方法，玩家实例中的广播状态的对象仅仅是团队成员.<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Send the Server->Client packet StatusUpdate with current HP, MP and CP to this L2PcInstance</li><BR>
	 * <li>Send the Server->Client packet PartySmallWindowUpdate with current HP, MP and Level to all other L2PcInstance of the Party</li><BR>
	 * <BR>
	 * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND current HP and MP to all L2PcInstance of the _statusListener</B></FONT><BR>
	 * <BR>
	 */
	@Override
	public void broadcastStatusUpdate() {
		// Send the Server->Client packet StatusUpdate with current HP and MP to
		// all L2PcInstance that must be informed of HP/MP updates of this
		// L2PcInstance
		super.broadcastStatusUpdate();

		// 通知自己HP、MP的情况
		StatusUpdate su = new StatusUpdate(getObjectId());
		su.addAttribute(StatusUpdate.HP, getCurrentHpRadio());
		su.addAttribute(StatusUpdate.MP, getCurrentMpRadio());
		sendPacket(su);

		// 检查是否在队伍里，如果是，则将自己的基础信息广播给队伍其他成员
		if (isInParty()) {
			if (_log.isDebugEnabled())
				_log.debug("Send status for party window of " + getObjectId() + "(" + getName() + ") to his party. CP: " + " HP: " + getCurrentHp() + " MP: " + getCurrentMp(), getObjectId(), getName());
			PartySmallWindowUpdate update = new PartySmallWindowUpdate(this);
			getParty().broadcastToPartyMembers(this, update);
		}
	}

	/**
	 * Send a Server->Client packet UserInfo to this L2PcInstance and CharInfo to all L2PcInstance in its _KnownPlayers.<BR>
	 * <BR>
	 * <B><U> Concept</U> :</B><BR>
	 * <BR>
	 * Others L2PcInstance in the detection area of the L2PcInstance are identified in <B>_knownPlayers</B>. In order to inform other players of this L2PcInstance state modifications, server just need to go through _knownPlayers to send Server->Client Packet<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Send a Server->Client packet UserInfo to this L2PcInstance (Public and Private Data)</li> <li>Send a Server->Client packet CharInfo to all L2PcInstance in _KnownPlayers of the L2PcInstance (Public data only)</li><BR>
	 * <BR>
	 * <FONT COLOR=#FF0000><B> <U>Caution</U> : DON'T SEND UserInfo packet to other players instead of CharInfo packet. Indeed, UserInfo packet contains PRIVATE DATA as MaxHP, STR, DEX...</B></FONT><BR>
	 * <BR>
	 */
	public final void broadcastUserInfo() {
		// 发送一个自己的用户信息给客户端
		// sendPacket(new UserInfo(this));
		//
		// // Send a Server->Client packet CharInfo to all L2PcInstance in
		// _KnownPlayers of the L2PcInstance
		// if (Config.DEBUG)
		// _log.fine("players to notify:" +
		// getKnownList().getKnownPlayers().size() +
		// " packet: [S] 03 CharInfo");
		//
		// broadcastPacket(new CharInfo(this));
		// broadcastPacket(new ExBrExtraUserInfo(this));
	}

	public final void broadcastTitleInfo() {
		// Send a Server->Client packet UserInfo to this L2PcInstance
		// sendPacket(new UserInfo(this));
		// sendPacket(new ExBrExtraUserInfo(this));
		//
		// // Send a Server->Client packet TitleUpdate to all L2PcInstance in
		// _KnownPlayers of the L2PcInstance
		// if (Config.DEBUG)
		// _log.fine("players to notify:" +
		// getKnownList().getKnownPlayers().size() +
		// " packet: [S] cc TitleUpdate");
		//
		// broadcastPacket(new NicknameChanged(this));
	}

	/**
	 * 对自己的已知列表区中的玩家广播一个数据包，此方法覆盖了L2Character的该方法，
	 */
	// Override
	// public final void broadcastPacket(L2GameServerPacket mov) {
	// //如果不是自己的角色信息则也发给自己
	// if (!(mov instanceof CharInfo))
	// sendPacket(mov);
	//
	// //如果包被标记位invisible则只发送给GM
	// mov.setInvisible(getAppearance().getInvisible());
	//
	// Collection<L2PcInstance> plrs =
	// getKnownList().getKnownPlayers().values();
	// for (L2PcInstance player : plrs) {
	// player.sendPacket(mov);
	// }
	//
	// }

	/**
	 * Send a Server->Client packet StatusUpdate to the L2PcInstance.<BR>
	 * <BR>
	 */
	@Override
	public void sendPacket(L2GameServerPacket packet) {
		if (_client != null) {
			if (!(packet instanceof SystemMessage) || (packet instanceof SystemMessage && getSwitchByChatCode(Say2.SYSTEM_CHANNEL)))
				_client.sendPacket(packet);
		}
	}

	/**
	 * 管理和其他玩家交流的任务.<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>If the private store is a STORE_PRIVATE_SELL, send a Server->Client PrivateBuyListSell packet to the L2PcInstance</li> <li>If the private store is a STORE_PRIVATE_BUY, send a Server->Client PrivateBuyListBuy packet to the L2PcInstance</li> <li>If the private store is a STORE_PRIVATE_MANUFACTURE, send a Server->Client RecipeShopSellList packet to the L2PcInstance</li><BR>
	 * <BR>
	 * 
	 * @param target
	 *            The L2Character targeted
	 */
	public void doInteract(L2Character target) {
		if (target instanceof FuzePcInstance) {
			FuzePcInstance temp = (FuzePcInstance) target;
			sendPacket(ActionFailed.STATIC_PACKET);
		} else {
			// _interactTarget=null should never happen but one never knows ^^;
			if (target != null)
				target.onAction(this);
		}
	}

	/**
	 * 管理自动拾取任务.<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Send a System Message to the L2PcInstance : YOU_PICKED_UP_S1_ADENA or YOU_PICKED_UP_S1_S2</li> <li>Add the Item to the L2PcInstance inventory</li> <li>Send a Server->Client packet InventoryUpdate to this L2PcInstance with NewItem (use a new slot) or ModifiedItem (increase amount)</li> <li>
	 * Send a Server->Client packet StatusUpdate to this L2PcInstance with current weight</li><BR>
	 * <BR>
	 * <FONT COLOR=#FF0000><B> <U>Caution</U> : If a Party is in progress, distribute Items between party members</B></FONT><BR>
	 * <BR>
	 * 
	 * @param target
	 *            The L2ItemInstance dropped
	 */
	public void doAutoLoot(L2Attackable target, ItemDropManage.RewardItem item) {

		if (isInParty())
			getParty().distributeItem(this, item, false, target);
		else
			addItem(ItemDropManage.DROP_STR, item.getItemId(), item.getCount(), target, true);
	}

	/**
	 * Manage Pickup Task.<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Send a Server->Client packet StopMove to this L2PcInstance</li> <li>
	 * Remove the L2ItemInstance from the world and send server->client GetItem packets</li> <li>Send a System Message to the L2PcInstance : YOU_PICKED_UP_S1_ADENA or YOU_PICKED_UP_S1_S2</li> <li>Add the Item to the L2PcInstance inventory</li> <li>Send a Server->Client packet InventoryUpdate to this L2PcInstance with NewItem (use a new slot) or ModifiedItem (increase amount)</li> <li>Send a Server->Client packet StatusUpdate to this L2PcInstance with current weight</li><BR>
	 * <BR>
	 * <FONT COLOR=#FF0000><B> <U>Caution</U> : If a Party is in progress, distribute Items between party members</B></FONT><BR>
	 * <BR>
	 * 
	 * @param object
	 *            The L2ItemInstance to pick up
	 */
	protected void doPickupItem(L2Object object) {
		if (isDead())
			return;

		// Set the AI Intention to AI_INTENTION_IDLE
		getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);

		// Check if the L2Object to pick up is a L2ItemInstance
		if (!(object instanceof L2ItemInstance)) {
			// dont try to pickup anything that is not an item :)
			_log.warn("trying to pickup wrong target." + getTarget(), getObjectId(), getName());
			return;
		}

		L2ItemInstance target = (L2ItemInstance) object;

		// Check if the target to pick up is visible
		if (!target.isVisible()) {
			// Send a Server->Client packet ActionFailed to this
			// L2PcInstance
			sendPacket(ActionFailed.STATIC_PACKET);
			return;
		}

		if (((isInParty() && getParty().getLootDistribution() == L2Party.ITEM_LOOTER) || !isInParty()) && !_inventory.validateCapacity(target)) {
			sendPacket(ActionFailed.STATIC_PACKET);
			sendPacket(new SystemMessage(SystemMessageId.SLOTS_FULL));
			return;
		}

		if (isInvul() && !isGM()) {
			sendPacket(ActionFailed.STATIC_PACKET);
			SystemMessage smsg = new SystemMessage(SystemMessageId.FAILED_TO_PICKUP_S1);
			smsg.addItemName(target);
			sendPacket(smsg);
			return;
		}

		if (target.getOwnerId() != 0 && target.getOwnerId() != getObjectId() && !isInLooterParty(target.getOwnerId())) {
			sendPacket(ActionFailed.STATIC_PACKET);

			if (target.getItemId() == 57) {
				SystemMessage smsg = new SystemMessage(SystemMessageId.FAILED_TO_PICKUP_S1_ADENA);
				smsg.addItemNumber(target.getCount());
				sendPacket(smsg);
			} else if (target.getCount() > 1) {
				SystemMessage smsg = new SystemMessage(SystemMessageId.FAILED_TO_PICKUP_S2_S1_S);
				smsg.addItemName(target);
				smsg.addItemNumber(target.getCount());
				sendPacket(smsg);
			} else {
				SystemMessage smsg = new SystemMessage(SystemMessageId.FAILED_TO_PICKUP_S1);
				smsg.addItemName(target);
				sendPacket(smsg);
			}

			return;
		}

		if (target.getItemLootShedule() != null && (target.getOwnerId() == getObjectId() || isInLooterParty(target.getOwnerId())))
			target.resetOwnerTimer();

		// Remove the L2ItemInstance from the world and send server->client
		// GetItem packets
		target.pickupMe(this);
		if (Config.SAVE_DROPPED_ITEM) // item must be removed from
			// ItemsOnGroundManager if is active
			ItemsOnGroundManager.getInstance().removeObject(target);

		// Auto use herbs - pick up
		// if item is instance of L2ArmorType or L2WeaponType broadcast an
		// "Attention" system message
		if (target.getItemType() instanceof L2ArmorType || target.getItemType() instanceof L2WeaponType) {
			if (target.getEnchantLevel() > 0) {
				SystemMessage msg = new SystemMessage(SystemMessageId.ANNOUNCEMENT_C1_PICKED_UP_S2_S3);
				msg.addPcName(this);
				msg.addNumber(target.getEnchantLevel());
				// msg.addItemName(target.getItemId());
				broadcastPacket(msg);
			} else {
				SystemMessage msg = new SystemMessage(SystemMessageId.ANNOUNCEMENT_C1_PICKED_UP_S2);
				msg.addPcName(this);
				// msg.addItemName(target.getItemId());
				broadcastPacket(msg);
			}
		}

		// Check if a Party is in progress
		// if (isInParty())
		// getParty().distributeItem(this, target);
		// Target is adena
		else if (target.getItemId() == 57 && getInventory().getMoneySilverInstance() != null) {
			addMoneySilver("Pickup", target.getCount(), null, true);
			ItemTable.getInstance().destroyItem("Pickup", target, this, null);
		}
		// Target is regular item
		else
			addItem("Pickup", target, null, true);

	}

	/*-----------------------------------变形处理部分-----------------------------------*/

	public boolean isTransformed() {
		return _transformation != null && !_transformation.isStance();
	}

	public boolean isInStance() {
		return _transformation != null && _transformation.isStance();
	}

	public void transform(L2Transformation transformation) {
		if (_transformation != null) {
			// You already polymorphed and cannot polymorph again.
			SystemMessage msg = new SystemMessage(SystemMessageId.YOU_ALREADY_POLYMORPHED_AND_CANNOT_POLYMORPH_AGAIN);
			sendPacket(msg);
			return;
		}
		if (isMounted()) {
			// Get off the strider or something else if character is mounted
			dismount();
		}

		_transformation = transformation;

		transformation.onTransform();
		sendSkillList();
		// sendPacket(new SkillCoolTime(this));
		broadcastUserInfo();
	}

	public void untransform() {
		if (_transformation != null) {
			setTransformAllowedSkills(new int[] {});
			_transformation.onUntransform();
			_transformation = null;
			stopEffects(L2EffectType.TRANSFORMATION);
			broadcastUserInfo();
			sendSkillList();
			// sendPacket(new SkillCoolTime(this));
		}
	}

	public L2Transformation getTransformation() {
		return _transformation;
	}

	/**
	 * This returns the transformation Id of the current transformation. For example, if a player is transformed as a Buffalo, and then picks up the Zariche, the transform Id returned will be that of the Zariche, and NOT the Buffalo.
	 * 
	 * @return Transformation Id
	 */
	public int getTransformationId() {
		return (_transformation == null ? 0 : _transformation.getId());
	}

	/**
	 * This returns the transformation Id stored inside the character table, selected by the method: transformSelectInfo() For example, if a player is transformed as a Buffalo, and then picks up the Zariche, the transform Id returned will be that of the Buffalo, and NOT the Zariche.
	 * 
	 * @return Transformation Id
	 */
	public int transformId() {
		return _transformationId;
	}

	// /**
	// * This is a simple query that inserts the transform Id into the character
	// * table for future reference.
	// */
	// public void transformInsertInfo() {
	// _transformationId = getTransformationId();
	//
	// if (_transformationId == L2Transformation.TRANSFORM_AKAMANAH ||
	// _transformationId == L2Transformation.TRANSFORM_ZARICHE)
	// return;
	//
	// Connection con = null;
	// try {
	// con = L2DatabaseFactory.getInstance().getConnection();
	// PreparedStatement statement =
	// con.prepareStatement(UPDATE_CHAR_TRANSFORM);
	//
	// statement.setInt(1, _transformationId);
	// statement.setLong(2, getObjectId());
	//
	// statement.execute();
	// statement.close();
	// } catch (Exception e) {
	// _log.log(Level.SEVERE, "Transformation insert info: ", e);
	// } finally {
	// try {
	// con.close();
	// } catch (Exception e) {
	// }
	// }
	// }

	// /**
	// * This selects the current
	// *
	// * @return transformation Id
	// */
	// public int transformSelectInfo() {
	// Connection con = null;
	// try {
	// con = L2DatabaseFactory.getInstance().getConnection();
	// PreparedStatement statement =
	// con.prepareStatement(SELECT_CHAR_TRANSFORM);
	//
	// statement.setLong(1, getObjectId());
	// ResultSet rset = statement.executeQuery();
	// rset.next();
	// _transformationId = rset.getInt("transform_id");
	//
	// rset.close();
	// statement.close();
	// } catch (Exception e) {
	// _log.log(Level.SEVERE, "Transformation select info: ", e);
	// } finally {
	// try {
	// con.close();
	// } catch (Exception e) {
	// }
	// }
	// return _transformationId;
	// }

	/**
	 * 设置目标.<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Remove the L2PcInstance from the _statusListener of the old target if it was a L2Character</li> <li>Add the L2PcInstance to the _statusListener of the new target if it's a L2Character</li> <li>Target the new L2Object (add the target to the L2PcInstance _target, _knownObject and L2PcInstance to _KnownObject of the L2Object)</li><BR>
	 * <BR>
	 * 
	 * @param newTarget
	 *            The L2Object to target
	 */
	@Override
	public void setTarget(L2Object newTarget) {
		// 获取当前的目标
		L2Object oldTarget = _target;

		if (oldTarget != null) {
			if (oldTarget == newTarget)
				return; // no target change

			// 如果当前目标是一个L2Character对象，那么把自己从当前的目标的HP,MP状态监听列表中删除
			if (oldTarget instanceof L2Character)
				((L2Character) oldTarget).removeStatusListener(this);
		}

		// Add the L2PcInstance to the _statusListener of the new target if it's
		// a L2Character
		if (newTarget instanceof L2Character) {
			((L2Character) newTarget).addStatusListener(this);
		}

		// Target the new L2Object (add the target to the L2PcInstance _target,
		// _knownObject and L2PcInstance to _KnownObject of the L2Object)
		super.setTarget(newTarget);
	}

	/**
	 * 返回激活的武器的实例对象（总是装备在右手）.Paperdoll-纸娃娃系统（任务状态窗口被称为此）<BR>
	 * <BR>
	 */
	@Override
	public L2ItemInstance getActiveWeaponInstance() {
		return getInventory().getPaperdollItem(Inventory.PAPERDOLL_HAND);
	}

	/**
	 * 返回激活的武器的实例的模板.<BR>
	 * <BR>
	 */
	@Override
	public L2Weapon getActiveWeaponItem() {
		L2ItemInstance weapon = getActiveWeaponInstance();

		if (weapon == null)
			return getFistsWeaponItem();

		return (L2Weapon) weapon.getItem();
	}

	/**
	 * 返回副武器实例(总是装备在做手).<BR>
	 * <BR>
	 */
	@Override
	public L2ItemInstance getSecondaryWeaponInstance() {
		return getInventory().getPaperdollItem(Inventory.PAPERDOLL_HAND);
	}

	/**
	 * 返回副武器实例的模板(always equiped in the left hand) or the fists weapon.<BR>
	 * <BR>
	 */
	@Override
	public L2Weapon getSecondaryWeaponItem() {
		L2ItemInstance weapon = getSecondaryWeaponInstance();

		if (weapon == null)
			return getFistsWeaponItem();

		L2Item item = weapon.getItem();

		if (item instanceof L2Weapon)
			return (L2Weapon) item;

		return null;
	}

	/**
	 * 返回人物装备的胸甲实例
	 * 
	 * @return
	 */
	public L2ItemInstance getChestArmorInstance() {
		return getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST);
	}

	/**
	 * 返回激活的胸甲的实例的模板.<BR>
	 * <BR>
	 */
	public L2Armor getActiveChestArmorItem() {
		L2ItemInstance armor = getChestArmorInstance();

		if (armor == null)
			return null;

		return (L2Armor) armor.getItem();
	}

	/**
	 * 返回人物装备的腿甲实例
	 * 
	 * @return
	 */
	public L2ItemInstance getLegsArmorInstance() {
		return getInventory().getPaperdollItem(Inventory.PAPERDOLL_LEGS);
	}

	/**
	 * 返回激活的腿甲的实例的模板.<BR>
	 * <BR>
	 */
	public L2Armor getActiveLegsArmorItem() {
		L2ItemInstance legs = getLegsArmorInstance();
		if (legs == null)
			return null;
		return (L2Armor) legs.getItem();
	}

	/*---------------------------结婚处理部分-------------------------*/

	/**
	 * 是否已经结婚
	 * 
	 * @return
	 */
	public boolean isMarried() {
		return _married;
	}

	/**
	 * 设置是否结婚
	 * 
	 * @param state
	 */
	public void setMarried(boolean state) {
		_married = state;
	}

	public boolean isEngageRequest() {
		return _engagerequest;
	}

	public void setEngageRequest(boolean state, int playerid) {
		_engagerequest = state;
		_engageid = playerid;
	}

	public void setMaryRequest(boolean state) {
		_marryrequest = state;
	}

	public boolean isMaryRequest() {
		return _marryrequest;
	}

	public void setMarryAccepted(boolean state) {
		_marryaccepted = state;
	}

	public boolean isMarryAccepted() {
		return _marryaccepted;
	}

	public int getEngageId() {
		return _engageid;
	}

	public long getPartnerId() {
		return _partnerId;
	}

	public void setPartnerId(long partnerid) {
		_partnerId = partnerid;
	}

	public long getCoupleId() {
		return _coupleId;
	}

	public void setCoupleId(long coupleId) {
		_coupleId = coupleId;
	}

	public void EngageAnswer(int answer) {
		if (_engagerequest == false)
			return;
		else if (_engageid == 0)
			return;
		else {
			FuzePcInstance ptarget = (FuzePcInstance) FuzeWorld.getInstance().findObject(_engageid);
			setEngageRequest(false, 0);
			if (ptarget != null) {
				if (answer == 1) {
					CoupleManager.getInstance().createCouple(ptarget, FuzePcInstance.this);
					ptarget.sendMessage("Request to Engage has been >ACCEPTED<");
				} else
					ptarget.sendMessage("Request to Engage has been >DENIED<!");
			}
		}
	}

	/*----------------------死亡处理部分---------------------------------------*/

	/**
	 * 死亡时的处理，杀掉一个角色，触发死亡惩罚，增减性向或道具掉落等逻辑.<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Reduce the Experience of the L2PcInstance in function of the calculated Death Penalty</li> <li>If necessary, unsummon the Pet of the killed L2PcInstance</li> <li>Manage Karma gain for attacker and Karam loss for the killed L2PcInstance</li> <li>If the killed L2PcInstance has Karma, manage Drop Item</li> <li>Kill the L2PcInstance</li><BR>
	 * <BR>
	 * 
	 * @param i
	 *            The HP decrease value
	 * @param attacker
	 *            The L2Character who attacks
	 * @see labox.innovation.gameserver.model.actor.L2Playable#doDie(labox.innovation.gameserver.model.actor.L2Character)
	 */
	@Override
	public boolean doDie(L2Character killer) {
		SystemMessage msg = null;
		// 检查超类的死亡情况
		if (!super.doDie(killer))
			return false;

		// 如果骑乘状态，停止喂养
		if (isMounted())
			stopFeed();

		if (killer != null) {
			FuzePcInstance pk = killer.getActingPlayer();
			// 发送好友消息
			if (killer instanceof FuzePcInstance) {
				if (getRace() == ((FuzePcInstance) killer).getRace()) {
					L2FriendsNewsManager.getInstance().sendMessage(FriendNewsFactory.creatDeadMessage(this, (FuzePcInstance) killer), null);
				}
				msg = new SystemMessage(SystemMessageId.TARGET_WAS_KILLED_YOU);
				msg.addCharName(this);
				((FuzePcInstance) killer).sendPacket(msg);
				msg = new SystemMessage(SystemMessageId.YOU_ARE_KILLED_TARGET);
				msg.addCharName(killer);
				sendPacket(msg);
			}
			if (atEvent && pk != null) {
				pk.kills.add(getName());
			}

			// onDieDropItem(killer); // 检查是否有道具需要掉落
			ItemDropManage.getInstance().dropItem(killer, this);

			// if (!isInsideZone(ZONE_PVP) || pk == null)
		}

		setPvpFlag(0); // 清除掉PVP标志
		updateEndurance(REDUCEENDU_DIE, -1);
		return true;
	}

	public void onKillUpdatePvPKarma(L2Character target) {
		if (target == null)
			return;
		if (!(target instanceof L2Playable))
			return;

		FuzePcInstance targetPlayer = target.getActingPlayer();

		if (targetPlayer == null)
			return; // Target player is null
		if (targetPlayer == this)
			return; // Target player is self

		// If in Arena, do nothing
		if (isInsideZone(ZONE_PVP) || targetPlayer.isInsideZone(ZONE_PVP))
			return;

		// Check if it's pvp
		if ((checkIfPvP(target) && // Can pvp and
				targetPlayer.getPvpFlag() != 0 // Target player has pvp flag set
				)
				|| // or
				(isInsideZone(ZONE_PVP) && // Player is inside pvp zone and
				targetPlayer.isInsideZone(ZONE_PVP) // Target player is inside
				// pvp zone
				)) {
			if (target instanceof FuzePcInstance)
				increasePvpKills();
		} else{// Target player doesn't have pvp flag set
			// check about wars
			if (targetPlayer.getClan() != null && getClan() != null && getClan().isAtWarWith(targetPlayer.getClanId()) && targetPlayer.getClan().isAtWarWith(getClanId())) {
				// 'Both way war' -> 'PvP Kill'
				if (target instanceof FuzePcInstance)
					increasePvpKills();
				return;
			}

			// 'No war' or 'One way war' -> 'Normal PK'
//			if (targetPlayer.getKarma() > 0) // Target player has karma
//			{
//				if (Config.KARMA_AWARD_PK_KILL) {
//					if (target instanceof FuzePcInstance)
//						increasePvpKills();
//				}
//			} else 
				if (targetPlayer.getPvpFlag() == 0){ // Target player doesn't have karma

				if (targetPlayer.getRace() == getRace() && targetPlayer.getKarmaStat() == KarmaStat.ERRANTRY) {// 只有杀死同种族白名玩家才会增加善恶值
					increasePkKillsAndKarma(targetPlayer.getLevel(), target instanceof FuzePcInstance);
				}
				// Unequip adventurer items
//				if (getInventory().getPaperdollItemId(7) >= 7816 && getInventory().getPaperdollItemId(7) <= 7831) {
//					L2ItemInstance invItem = getInventory().getItemByItemId(getInventory().getPaperdollItemId(7));
//					if (invItem.isEquipped()) {
//						L2ItemInstance[] unequiped = getInventory().unEquipItemInSlotAndRecord(invItem.getLocationSlot());
//						// InventoryUpdate iu = new InventoryUpdate();
//						// for (L2ItemInstance itm : unequiped)
//						// iu.addModifiedItem(itm);
//						// sendPacket(iu);
//					}
//					sendPacket(new SystemMessage(SystemMessageId.YOU_ARE_UNABLE_TO_EQUIP_THIS_ITEM_WHEN_YOUR_PK_COUNT_IS_GREATER_THAN_OR_EQUAL_TO_ONE));
//				}
			}
		}
	}

	/**
	 * Return the the PvP Kills of the L2PcInstance (Number of player killed during a PvP).<BR>
	 * <BR>
	 */
	public int getPvpKills() {
		return _pvpKills;
	}

	/**
	 * Set the the PvP Kills of the L2PcInstance (Number of player killed during a PvP).<BR>
	 * <BR>
	 */
	public void setPvpKills(int pvpKills) {
		_pvpKills = pvpKills;
	}

	/**
	 * 增加pvp杀人的数量，并发送信息给自己的客户端
	 */
	private void increasePvpKills() {
		// Add karma to attacker and increase its PK counter
		setPvpKills(getPvpKills() + 1);

		// Send a Server->Client UserInfo packet to attacker with its Karma and
		// PK Counter
		// sendPacket(new UserInfo(this));
		// sendPacket(new ExBrExtraUserInfo(this));
	}

	/**
	 * Increase pk count, karma and send the info to the player
	 * 
	 * @param targLVL
	 *            : level of the killed player
	 * @param increasePk
	 *            : true if PK counter should be increased too
	 */
	private void increasePkKillsAndKarma(int targLVL, boolean increasePk) {
		int baseKarma = Config.KARMA_MIN_KARMA;
		int newKarma = baseKarma;
		int karmaLimit = Config.KARMA_MAX_KARMA;

		int pkLVL = getLevel();

		int lvlDiffMulti = (int) ((pkLVL - targLVL) / 10.0 + 0.5);
		newKarma += lvlDiffMulti;

		// Add karma to attacker and increase its PK counter
		if (getKarma() + newKarma > karmaLimit) {
			setKarma(karmaLimit);
			getPunish().setPunishLevel(Punish.PunishLevel.JAIL, 0);//达到最大的仇恨值后投入监狱
		} else {
			setKarma(getKarma() + newKarma);
		}
		if (increasePk)
			setPkKills(getPkKills() + 1);

	}

	/**
	 * 更新pvp状态
	 */
	public void updatePvPStatus() {
		if (isInsideZone(ZONE_PVP))
			return;
		setPvpFlagLasts(System.currentTimeMillis() + Config.PVP_NORMAL_TIME);
		if (getPvpFlag() == 0)
			startPvPFlag();
	}

	public void updatePvPStatus(L2Character target) {
		FuzePcInstance player_target = target.getActingPlayer();

		if (player_target == null)
			return;

		if ((!isInsideZone(ZONE_PVP) || !player_target.isInsideZone(ZONE_PVP)) && player_target.getKarma() == 0) {
			if (checkIfPvP(player_target))
				setPvpFlagLasts(System.currentTimeMillis() + Config.PVP_PVP_TIME);
			else
				setPvpFlagLasts(System.currentTimeMillis() + Config.PVP_NORMAL_TIME);
			if (getPvpFlag() == 0)
				startPvPFlag();
		}
	}

	/**
	 * 停止所有的定时器任务.<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Set the RegenActive flag to False</li> <li>Stop the HP/MP/CP Regeneration task</li><BR>
	 * <BR>
	 */
	public void stopAllTimers() {
		getStatus().stopRegeneration();
		stopFeed();
		clearPetData();
		stopPvpRegTask();
		getPunish().stopPunishTask();
	}

	/**
	 * Return the L2Summon of the L2PcInstance or null.<BR>
	 * <BR>
	 */
	@Override
	public L2Summon getPet() {
		return _summon;
	}

	/**
	 * Return the L2Decoy of the L2PcInstance or null.<BR>
	 * <BR>
	 */
	public L2Decoy getDecoy() {
		return _decoy;
	}

	/**
	 * Return the L2Trap of the L2PcInstance or null.<BR>
	 * <BR>
	 */
	public L2Trap getTrap() {
		return _trap;
	}

	/**
	 * Set the L2Summon of the L2PcInstance.<BR>
	 * <BR>
	 */
	public void setPet(L2Summon summon) {
		_summon = summon;
		// update attack element value display
		// if ((_summon == null || _summon instanceof L2SummonInstance) &&
		// getClassId().isSummoner() && getAttackElement() != Elementals.NONE)
		// sendPacket(new UserInfo(this));

	}

	/**
	 * Set the L2Decoy of the L2PcInstance.<BR>
	 * <BR>
	 */
	public void setDecoy(L2Decoy decoy) {
		_decoy = decoy;
	}

	/**
	 * Set the L2Trap of this L2PcInstance<BR>
	 * <BR>
	 * 
	 * @param trap
	 */
	public void setTrap(L2Trap trap) {
		_trap = trap;
	}

	/**
	 * Return the L2Summon of the L2PcInstance or null.<BR>
	 * <BR>
	 */
	public L2TamedBeastInstance getTrainedBeast() {
		return _tamedBeast;
	}

	/**
	 * Set the L2Summon of the L2PcInstance.<BR>
	 * <BR>
	 */
	public void setTrainedBeast(L2TamedBeastInstance tamedBeast) {
		_tamedBeast = tamedBeast;
	}

	/**
	 * Return the L2PcInstance requester of a transaction (ex : FriendInvite, JoinAlly, JoinParty...).<BR>
	 * <BR>
	 */
	public L2Request getRequest() {
		return _request;
	}

	/**
	 * Set the L2PcInstance requester of a transaction (ex : FriendInvite, JoinAlly, JoinParty...).<BR>
	 * <BR>
	 */
	public void setActiveRequester(FuzePcInstance requester) {
		_activeRequester = requester;
	}

	/**
	 * Return the L2PcInstance requester of a transaction (ex : FriendInvite, JoinAlly, JoinParty...).<BR>
	 * <BR>
	 */
	public FuzePcInstance getActiveRequester() {
		return _activeRequester;
	}

	/**
	 * Return True if a transaction is in progress.<BR>
	 * <BR>
	 */
	public boolean isProcessingRequest() {
		return _activeRequester != null || _requestExpireTime > GameTimeController.getGameTicks();
	}

	/**
	 * Return True if a transaction is in progress.<BR>
	 * <BR>
	 */
	public boolean isProcessingTransaction() {
		return _activeRequester != null || _activeTradeList != null || _requestExpireTime > GameTimeController.getGameTicks();
	}

	/**
	 * Select the Warehouse to be used in next activity.<BR>
	 * <BR>
	 */
	public void onTransactionRequest(FuzePcInstance partner) {
		_requestExpireTime = GameTimeController.getGameTicks() + REQUEST_TIMEOUT * GameTimeController.TICKS_PER_SECOND;
		partner.setActiveRequester(this);
	}

	/**
	 * Return true if last request is expired.
	 * 
	 * @return
	 */
	public boolean isRequestExpired() {
		return !(_requestExpireTime > GameTimeController.getGameTicks());
	}

	/**
	 * Select the Warehouse to be used in next activity.<BR>
	 * <BR>
	 */
	public void onTransactionResponse() {
		_requestExpireTime = 0;
	}

	/**
	 * Select the Warehouse to be used in next activity.<BR>
	 * <BR>
	 */
	public void setActiveWarehouse(ItemContainer warehouse) {
		_activeWarehouse = warehouse;
	}

	/**
	 * Return active Warehouse.<BR>
	 * <BR>
	 */
	public ItemContainer getActiveWarehouse() {
		return _activeWarehouse;
	}

	/**
	 * Select the TradeList to be used in next activity.<BR>
	 * <BR>
	 */
	public void setActiveTradeList(TradeList tradeList) {
		_activeTradeList = tradeList;
	}

	/**
	 * 设置角色身上的 有效锻造链表
	 * 
	 * @param forgeList
	 */
	public void setActiveForgeItemList(ForgeItemList forgeList) {
		_activeForgeList = forgeList;
	}

	/**
	 * 获得玩家身上的有效锻造链表
	 * 
	 * @return
	 */
	public ForgeItemList getActiveForgeItemList() {
		return _activeForgeList;
	}

	/**
	 * Return active TradeList.<BR>
	 * <BR>
	 */
	public TradeList getActiveTradeList() {
		return _activeTradeList;
	}

	public void onTradeStart(FuzePcInstance partner) {
		_activeTradeList = new TradeList(this);
		_activeTradeList.setPartner(partner);

		SystemMessage msg = new SystemMessage(SystemMessageId.BEGIN_TRADE_WITH_C1);
		msg.addPcName(partner);
		sendPacket(msg);
		sendPacket(new TradeStart(this));
	}

	public void onTradeConfirm(FuzePcInstance partner) {
		// SystemMessage msg = new SystemMessage(
		// SystemMessageId.C1_CONFIRMED_TRADE);
		// msg.addPcName(partner);
		// sendPacket(msg);
		sendPacket(new TradeStats(TradeStats.STAT_IN_TRADE, TradeStats.STAT_PARTEN));
	}

	public void onTradeCancel(FuzePcInstance partner) {
		if (_activeTradeList == null)
			return;

		_activeTradeList.unLock();
		_activeTradeList = null;

		sendPacket(new TradeDone(0));
		SystemMessage msg = new SystemMessage(SystemMessageId.C1_CANCELED_TRADE);
		msg.addPcName(partner);
		sendPacket(msg);
	}

	public void onTradeFinish(boolean successfull) {
		_activeTradeList = null;
		int flag = 1;
		if (!successfull)
			flag = 0;
		sendPacket(new TradeDone(flag));
		if (successfull)
			sendPacket(new SystemMessage(SystemMessageId.TRADE_SUCCESSFUL));
	}

	public void startTrade(FuzePcInstance partner) {
		onTradeStart(partner);
		partner.onTradeStart(this);
	}

	/**
	 * 自动挂机购买物品接口
	 * 
	 * @param itemID
	 * @param count
	 */
	public void buyItemsAuto(int itemID, int count) {
		float _storeBuyRate = this.getTemplate().getBaseShopBuyRate();
		int karma = this.getKarma(); // -- 获取当前玩家身上的善恶值

		if (karma >= Config.KARMAREDSSET) {
			_storeBuyRate = (float) ((Config.KARMABASE + karma) / Config.KARMABASE);
		}
		L2Item item = ItemTable.getInstance().getTemplate(itemID);
		int buyPrice = Math.round(item.getBuyPrice() * _storeBuyRate * count); // -- 计算银元数

		if (this.getInventory().validateCapacityByItemId(itemID, count)) { // -- 判断背包是否已满
			if (this.getMoneySilver() + this.getMoneyNote() >= buyPrice) {
				if (this.reduceMoneySilver(FuzeEconomicManager.OPSTATE.TRADE.getValue(), buyPrice, this, false)) { // -- 扣钱
					this.addItem(FuzeEconomicManager.OPSTATE.TRADE.getValue(), itemID, count, this, false); // -- 买入物品
					this.sendMessage("自动购买" + item.getName() + "x50");
				}
			}
		} else {
			this.sendPacket(new SystemMessage(SystemMessageId.INVENTORY_IS_FULL)); // -- 背包满
		}
	}

	public void cancelActiveTrade() {
		if (_activeTradeList == null)
			return;
		FuzePcInstance partner = _activeTradeList.getPartner();
		if (partner != null)
			partner.onTradeCancel(this);
		onTradeCancel(this);
	}

	/**
	 * 设置加入的帮会Set the _clan object, _clanId, _clanLeader Flag and title of the L2PcInstance.<BR>
	 * <BR>
	 */
	public void setClan(L2Clan clan) {
		_clan = clan;
		setTitle("");

		if (clan == null) {
			_clanId = 0;
			_clanPrivileges = 0;
			_apprentice = 0;
			_sponsor = 0;
			return;
		}

		if (!clan.isMember(getObjectId())) {
			// char has been kicked from clan
			setClan(null);
			return;
		}

		_clanId = clan.getClanId();
	}

	/**
	 * 返回玩家所在的帮会<BR>
	 * <BR>
	 */
	public L2Clan getClan() {
		return _clan;
	}

	/**
	 * 是否玩家为一个帮会的头领.<BR>
	 * <BR>
	 */
	public boolean isClanLeader() {
		if (getClan() == null) {
			return false;
		} else {
			return getObjectId() == getClan().getLeaderId();
		}
	}

	/**
	 * 卸下玩家手上的武器.<BR>
	 * <BR>
	 */
	public boolean disarmWeapons() {

		// Unequip the weapon
		L2ItemInstance wpn = getInventory().getPaperdollItem(Inventory.PAPERDOLL_HAND);
		if (wpn == null)
			wpn = getInventory().getPaperdollItem(Inventory.PAPERDOLL_HAND);
		if (wpn != null) {
			if (wpn.isWear())
				return false;

			L2ItemInstance[] unequiped = getInventory().unEquipItemInBodySlotAndRecord(wpn.getItem().getBodyPart());
			// InventoryUpdate iu = new InventoryUpdate();
			// for (L2ItemInstance itm : unequiped)
			// iu.addModifiedItem(itm);
			// sendPacket(iu);
			broadcastUserInfo();

			// this can be 0 if the user pressed the right mousebutton twice
			// very fast
			if (unequiped.length > 0) {
				SystemMessage sm = null;
				if (unequiped[0].getEnchantLevel() > 0) {
					sm = new SystemMessage(SystemMessageId.EQUIPMENT_S1_S2_REMOVED);
					sm.addNumber(unequiped[0].getEnchantLevel());
					sm.addItemName(unequiped[0]);
				} else {
					sm = new SystemMessage(SystemMessageId.S1_DISARMED);
					sm.addItemName(unequiped[0]);
				}
				sendPacket(sm);
			}
		}
		return true;
	}

	public boolean mount(L2Summon pet) {
		if (!disarmWeapons())// 先卸下武器
			return false;
		if (isTransformed())// 不能是变形状态
			return false;

		// Ride mount = new Ride(this, true, pet.getTemplate().id);
		// setMount(pet.getNpcId(), pet.getLevel(), mount.getMountType());
		// setMountObjectID(pet.getControlItemId());
		// clearPetData();
		// startFeed(pet.getNpcId());//开始启动喂养的服务
		// broadcastPacket(mount);

		// Notify self and others about speed change
		broadcastUserInfo();

		pet.unSummon(this);

		return true;
	}

	public boolean mount(int npcId, int controlItemObjId, boolean useFood) {
		if (!disarmWeapons())
			return false;
		if (isTransformed())
			return false;

		// Ride mount = new Ride(this, true, npcId);
		// if (setMount(npcId, getLevel(), mount.getMountType())) {
		// clearPetData();
		// setMountObjectID(controlItemObjId);
		// broadcastPacket(mount);
		//
		// // Notify self and others about speed change
		// broadcastUserInfo();
		// if (useFood)
		// startFeed(npcId);
		// return true;
		// }
		return false;
	}

	public boolean mountPlayer(L2Summon pet) {
		if (pet != null && pet.isMountable() && !isMounted() && !isBetrayed()) {
			if (isDead()) {
				// A strider cannot be ridden when dead
				sendPacket(new SystemMessage(SystemMessageId.STRIDER_CANT_BE_RIDDEN_WHILE_DEAD));
				return false;
			} else if (pet.isDead()) {
				// A dead strider cannot be ridden.
				sendPacket(new SystemMessage(SystemMessageId.DEAD_STRIDER_CANT_BE_RIDDEN));
				return false;
			} else if (pet.isInCombat() || pet.isRooted()) {
				// A strider in battle cannot be ridden
				sendPacket(new SystemMessage(SystemMessageId.STRIDER_IN_BATLLE_CANT_BE_RIDDEN));
				return false;

			} else if (isInCombat()) {
				// A strider cannot be ridden while in battle
				sendPacket(new SystemMessage(SystemMessageId.STRIDER_CANT_BE_RIDDEN_WHILE_IN_BATTLE));
				return false;
			} else if (isTransformed()) {
				// no message needed, player while transformed doesn't have
				// mount action
				return false;
			} else if (getInventory().getItemByItemId(9819) != null) {
				sendPacket(new SystemMessage(SystemMessageId.YOU_CANNOT_MOUNT_A_STEED_WHILE_HOLDING_A_FLAG)); // TODO:
				// confirm
				// this
				// message
				return false;
			} else if (pet.isHungry()) {
				sendPacket(new SystemMessage(SystemMessageId.HUNGRY_STRIDER_NOT_MOUNT));
				return false;
			} else if (!Util.checkIfInRange(200, this, pet)) {
				sendPacket(new SystemMessage(SystemMessageId.TOO_FAR_AWAY_FROM_FENRIR_TO_MOUNT));
				return false;
			} else if (!pet.isDead() && !isMounted()) {
				mount(pet);
			}
		} else if (isMounted()) {
			if (getMountType() == 2 && this.isInsideZone(L2Character.ZONE_NOLANDING)) {
				sendPacket(new SystemMessage(SystemMessageId.NO_DISMOUNT_HERE));
				return false;
			} else if (isHungry()) {
				sendPacket(new SystemMessage(SystemMessageId.HUNGRY_STRIDER_NOT_MOUNT));
				return false;
			} else
				dismount();
		}
		return true;
	}

	public boolean dismount() {

		// sendPacket(new SetupGauge(3, 0, 0));
		// int petId = _mountNpcId;
		// if (setMount(0, 0, 0)) {
		// stopFeed();
		// clearPetData();
		//
		// Ride dismount = new Ride(this, false, 0);
		// broadcastPacket(dismount);
		// setMountObjectID(0);
		// storePetFood(petId);
		// // Notify self and others about speed change
		// broadcastUserInfo();
		// return true;
		// }
		return false;
	}

	public void setUptime(long time) {
		_uptime = time;
	}

	public long getUptime() {
		return System.currentTimeMillis() - _uptime;
	}

	/**
	 * Return True if the L2PcInstance is invulnerable.<BR>
	 * <BR>
	 */
	@Override
	public boolean isInvul() {
		return super.isInvul() || isTeleporting() || isSpawnProtected();
	}

	/**
	 * Return True if the L2PcInstance has a Party in progress.<BR>
	 * <BR>
	 */
	@Override
	public boolean isInParty() {
		return _party != null;
	}

	/**
	 * Set the _party object of the L2PcInstance (without joining it).<BR>
	 * <BR>
	 */
	public void setParty(L2Party party) {
		_party = party;
	}

	/**
	 * Set the _party object of the L2PcInstance AND join it.<BR>
	 * <BR>
	 */
	public void joinParty(L2Party party) {
		if (party != null) {
			// First set the party otherwise this wouldn't be considered
			// as in a party into the L2Character.updateEffectIcons() call.
			_party = party;
			party.addPartyMember(this);
		}
	}

	/**
	 * Manage the Leave Party task of the L2PcInstance.<BR>
	 * <BR>
	 */
	public void leaveParty() {
		if (isInParty()) {
			_party.removePartyMember(this);
			_party = null;
		}
	}

	/**
	 * Return the _party object of the L2PcInstance.<BR>
	 * <BR>
	 */
	@Override
	public L2Party getParty() {
		return _party;
	}

	/**
	 * Return True if the L2PcInstance is a GM.<BR>
	 * <BR>
	 */
	public boolean isGM() {
		return getAccessLevel().isGm();
	}

	/**
	 * 设置玩家的连接权限等级<BR>
	 * <BR>
	 */
	public void setAccessLevel(int level) {
		if (level == AccessLevels._masterAccessLevelNum) {//设置GM的权限
			_log.warn("Master access level set for character " + getName() + "! Just a warning to be careful ;)", getObjectId(), getName());
			_accessLevel = AccessLevels._masterAccessLevel;
		} else if (level == AccessLevels._userAccessLevelNum)//设置一般用户权限
			_accessLevel = AccessLevels._userAccessLevel;
		else {
			L2AccessLevel accessLevel = AccessLevels.getInstance().getAccessLevel(level);

			if (accessLevel == null) {
				if (level < 0) {
					AccessLevels.getInstance().addBanAccessLevel(level);
					_accessLevel = AccessLevels.getInstance().getAccessLevel(level);
				} else {
					_log.warn("Tryed to set unregistered access level " + level + " to character " + getName() + ". Setting access level without privileges!", getObjectId(), getName());
					_accessLevel = AccessLevels._userAccessLevel;
				}
			} else
				_accessLevel = accessLevel;
		}

		if (_accessLevel != AccessLevels._userAccessLevel) {
			getAppearance().setNameColor(_accessLevel.getNameColor());
			getAppearance().setTitleColor(_accessLevel.getTitleColor());
			broadcastUserInfo();
		}
	}

	/**
	 * 发送给登陆服务器账户的连接权限等级
	 * 
	 * @param level
	 */
	public void setAccountAccesslevel(int level) {
		LoginServerThread.getInstance().sendAccessLevel(getAccountName(), level);
	}

	/**
	 * 返回此角色的 _accessLevel权限.<BR>
	 * <BR>
	 */
	public L2AccessLevel getAccessLevel() {
		if (Config.EVERYBODY_HAS_ADMIN_RIGHTS)
			return AccessLevels._masterAccessLevel;
		else if (_accessLevel == null) /* This is here because inventory etc. is loaded before access level on login, so it is not null */
			setAccessLevel(AccessLevels._userAccessLevelNum);
		return _accessLevel;
	}

	/**
	 * Update Stats of the L2PcInstance client side by sending Server->Client packet UserInfo/StatusUpdate to this L2PcInstance and CharInfo/StatusUpdate to all L2PcInstance in its _KnownPlayers (broadcast).<BR>
	 * <BR>
	 */
	public void updateAndBroadcastStatus(int broadcastType) {
		// Send a Server->Client packet UserInfo to this L2PcInstance and
		// CharInfo to all L2PcInstance in its _KnownPlayers (broadcast)
		if (broadcastType == 1) {
			// sendPacket(new UserInfo(this));
			// sendPacket(new ExBrExtraUserInfo(this));
		}
		if (broadcastType == 2)
			broadcastUserInfo();
	}

	/**
	 * Set the online Flag to True or False and update the characters table of the database with online status and lastAccess (called when login and logout).<BR>
	 * <BR>
	 */
	public void setOnlineStatus(boolean isOnline) {
		if (_isOnline != isOnline)
			_isOnline = isOnline;
		updateOnlineStatus();
	}

	/**
	 * Update the characters table of the database with online status and lastAccess of this L2PcInstance (called when login and logout).<BR>
	 * <BR>
	 */
	public void updateOnlineStatus() {
		ThreadPoolManager.getInstance().execute(new UpdateOnlineStatus(this));
	}

	public void reInitCharStatusUpdate() {
		getStat().initCharStatusUpdateValues();
		super.reInitCharStatusUpdate();
	}

	/**
	 * Create a new player in the characters table of the database.<BR>
	 * <BR>
	 */
	private boolean createDb() {
		try {
			PlayerDb.createplayer(this);
		} catch (Exception e) {
			_log.error("Could not insert char data: ", getObjectId(), e);
			return false;
		}
		return true;
	}

	/**
	 * Retrieve a L2PcInstance from the characters table of the database and add it in _allObjects of the L2world.<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Retrieve the L2PcInstance from the characters table of the database</li> <li>Add the L2PcInstance object in _allObjects</li> <li>Set the x,y,z position of the L2PcInstance and make it invisible</li> <li>Update the overloaded status of the L2PcInstance</li><BR>
	 * <BR>
	 * 
	 * @param objectId
	 *            Identifier of the object to initialized
	 * @return The L2PcInstance loaded from the database
	 */
	private static FuzePcInstance restore(long objectId) {
		FuzePcInstance player = null;

		try {
			player = PlayerDb.restoreplayer(objectId);
			if (player == null) {
				return null;
			}
			player.getInventory().restore();

			player.getWarehouse();
			// player.getFreight();

			player.restoreCharData();
			// player.rewardSkills();

			player.reInitCharStatusUpdate();

			// buff and status icons
			if (Config.STORE_SKILL_COOLTIME)
				// player.restoreEffects();
				PlayerSkills.restoreEffects(player);

			// Restore pet if exists in the world
			player.setPet(FuzeWorld.getInstance().getPet(player.getObjectId()));
			if (player.getPet() != null)
				player.getPet().setOwner(player);

			player.getFriendInstance().load();// 加载好友数据
			PlayerQuest.restoreQuest(player);
			Quest.playerEnter(player);// 加载任务数据
			player.refreshMayQuestList();// 刷新可接任务列表
			player.refreshQuestList();// 刷新已经任务列表
			CombatSetDAO.load(player);// 加载自动战斗数据
			player.getStatus().setCurrentHp(player.getCurrentHpTem(), false);
			player.getStatus().setCurrentMp(player.getCurrentMpTem(), false);
			PropGrantDAO.LoadCharacterProp(player);// 加载离线发送给角色的物品
		} catch (Exception e) {
			// 如果角色相关信息加载不完整，将player设置为null,以保证数据的完整性
			player = null;
			_log.error("Failed loading character.", Config.SERVER_ID, e);

		}

		return player;
	}

	/**
	 * @return
	 */
	public Forum getMail() {
		// if (_forumMail == null) {
		// setMail(ForumsBBSManager.getInstance().getForumByName("MailRoot").getChildByName(getName()));
		//
		// if (_forumMail == null) {
		// ForumsBBSManager.getInstance().createNewForum(getName(),
		// ForumsBBSManager.getInstance().getForumByName("MailRoot"),
		// Forum.MAIL, Forum.OWNERONLY, getObjectId());
		// setMail(ForumsBBSManager.getInstance().getForumByName("MailRoot").getChildByName(getName()));
		// }
		// }

		return _forumMail;
	}

	/**
	 * @param forum
	 */
	public void setMail(Forum forum) {
		_forumMail = forum;
	}

	/**
	 * Restores secondary data for the L2PcInstance, based on the current class index.
	 */
	private void restoreCharData() {
		// Retrieve from the database all skills of this L2PcInstance and add
		// them to _skills.
		// restoreSkills();
		PlayerSkills.restoreSkill(this);
		// Retrieve from the database all shortCuts of this L2PcInstance and add
		// them to _shortCuts.
		// _shortCuts.restore();
	}

	public synchronized void store() {
		store(true);
		// if (Config.UPDATE_ITEMS_ON_CHAR_STORE) {
		ItemsDb.updateitemContainer(getInventory(), getWarehouse(), getObjectId());
		// }
	}

	/**
	 * Update L2PcInstance stats in the characters table of the database.<BR>
	 * <BR>
	 *执行数据库操作。
	 */
	public void store(boolean storeActiveEffects) {
		storeCharBase();
		saveQuestEvent();
		getFriendInstance().save();// 保存好友
		// storeEffect(storeActiveEffects);
		PlayerSkills.storeEffect(storeActiveEffects, this);
		PlayerQuest.storeQuest(this);
		PlayerSkills.storeSkill(this);
		CombatSetDAO.saveOrUpadte(this);// 保存自动战斗配置数据
		// PlayerDb.updateOnlineStatus(this);//更新人物状态
		// transformInsertInfo();

	}

	private void storeCharBase() {
		try {
			// PlayerUpdate playerUpdate = new PlayerUpdate();
			// playerUpdate.setPlayer(this);
			// playerUpdate.run();
			PlayerDb.storeplayer(this);
		} catch (Exception e) {
			_log.error("Could not store char base data: ", getObjectId(), e);
		}
	}

	/**
	 * Return True if the L2PcInstance is on line.<BR>
	 * <BR>
	 */
	public int isOnline() {
		return (_isOnline ? 1 : 0);
	}

	/**
	 * Add a skill to the L2PcInstance _skills and its Func objects to the calculator set of the L2PcInstance and save update in the character_skills table of the database.<BR>
	 * <BR>
	 * <B><U> Concept</U> :</B><BR>
	 * <BR>
	 * All skills own by a L2PcInstance are identified in <B>_skills</B><BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Replace oldSkill by newSkill or Add the newSkill</li> <li>If an old skill has been replaced, remove all its Func objects of L2Character calculator set</li> <li>Add Func objects of newSkill to the calculator set of the L2Character</li><BR>
	 * <BR>
	 * 
	 * @param newSkill
	 *            The L2Skill to add to the L2Character
	 * @return The L2Skill replaced or null if just added a new L2Skill
	 */
	public L2Skill addSkill(L2Skill newSkill, boolean store) {
		// Add a skill to the L2PcInstance _skills and its Func objects to the
		// calculator set of the L2PcInstance
		L2Skill oldSkill = super.addSkill(newSkill);
		// Add or update a L2PcInstance skill in the character_skills table of
		// the database
		// if (store)
		// storeSkill(newSkill, oldSkill, -1);
		return oldSkill;
	}

	public L2Skill removeSkill(L2Skill skill, boolean store) {
		if (store)
			return removeSkill(skill);
		else
			return super.removeSkill(skill, true);
	}

	public L2Skill removeSkill(L2Skill skill, boolean store, boolean cancelEffect) {
		if (store)
			return removeSkill(skill);
		else
			return super.removeSkill(skill, cancelEffect);
	}

	/**
	 * Remove a skill from the L2Character and its Func objects from calculator set of the L2Character and save update in the character_skills table of the database.<BR>
	 * <BR>
	 * <B><U> Concept</U> :</B><BR>
	 * <BR>
	 * All skills own by a L2Character are identified in <B>_skills</B><BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Remove the skill from the L2Character _skills</li> <li>Remove all its Func objects from the L2Character calculator set</li><BR>
	 * <BR>
	 * <B><U> Overridden in </U> :</B><BR>
	 * <BR>
	 * <li>L2PcInstance : Save update in the character_skills table of the database</li><BR>
	 * <BR>
	 * 
	 * @param skill
	 *            The L2Skill to remove from the L2Character
	 * @return The L2Skill removed
	 */
	@Override
	public L2Skill removeSkill(L2Skill skill) {
		// Remove a skill from the L2Character and its Func objects from
		// calculator set of the L2Character
		L2Skill oldSkill = super.removeSkill(skill);

		// Connection con = null;
		//
		// try {
		// // Remove or update a L2PcInstance skill from the character_skills
		// // table of the database
		// con = L2DatabaseFactory.getInstance().getConnection();
		// PreparedStatement statement =
		// con.prepareStatement(DELETE_SKILL_FROM_CHAR);
		//
		// if (oldSkill != null) {
		// statement.setInt(1, oldSkill.getId());
		// statement.setLong(2, getObjectId());
		// statement.execute();
		// }
		// statement.close();
		// } catch (Exception e) {
		// _log.warning("Error could not delete skill: " + e);
		// } finally {
		// try {
		// con.close();
		// } catch (Exception e) {
		// }
		// }

		if (this.transformId() > 0)
			return oldSkill;

		for (L2ShortCut sc : getAllShortCuts()) {
			if (sc != null && skill != null && sc.getId() == skill.getId() && sc.getType() == L2ShortCut.TYPE_SKILL)
				_shortCuts.deleteShortCut(sc.getSlot(), true);
		}

		return oldSkill;
	}

	/**
	 * 检查一个attacker是否有能力攻击此玩家对象.<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Check if the attacker isn't the L2PcInstance Pet</li> <li>Check if the attacker is L2MonsterInstance</li> <li>If the attacker is a L2PcInstance, check if it is not in the same party</li> <li>Check if the L2PcInstance has Karma</li> <li>If the attacker is a L2PcInstance, check if it is not in the same siege clan (Attacker, Defender)</li><BR>
	 * <BR>
	 */
	@Override
	public boolean isAutoAttackable(L2Character attacker) {
		if (attacker instanceof FuzePcInstance) {
			
			if ( !isAttackByPc() && attacker.getObjectId() != getObjectId() ) {
				attacker.sendMessage("目标处于免疫PK状态");
				return false;
			}

			if ( !((FuzePcInstance) attacker).isAttackByPc() && attacker.getObjectId() != getObjectId() ) {
				attacker.sendMessage("处于免疫PK状态，不能攻击其他人");
				return false;
			}
			
			if (!getPkInstance().isArbitrarilyDefined((FuzePcInstance) attacker)) {
				if (getPkInstance().checkPkTypeAllowAttackable((FuzePcInstance) attacker)) {
					return true;
				} else {
					return false;
				}
			} else {
				
				return false;
				
			}

		} else
			return true;

	}

	/**
	 * Check if the active L2Skill can be casted.<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Check if the skill isn't toggle and is offensive</li> <li>Check if the target is in the skill cast range</li> <li>Check if the skill is Spoil type and if the target isn't already spoiled</li> <li>Check if the caster owns enought consummed Item, enough HP and MP to cast the skill</li> <li>Check if the caster isn't sitting</li> <li>Check if all skills are enabled and this skill is enabled</li><BR>
	 * <BR>
	 * <li>Check if the caster own the weapon needed</li><BR>
	 * <BR>
	 * <li>Check if the skill is active</li><BR>
	 * <BR>
	 * <li>Check if all casting conditions are completed</li><BR>
	 * <BR>
	 * <li>Notify the AI with AI_INTENTION_CAST and target</li><BR>
	 * <BR>
	 * 
	 * @param skill
	 *            The L2Skill to use
	 * @param forceUse
	 *            used to force ATTACK on players
	 * @param dontMove
	 *            used to prevent movement, if not in range 使用技能魔法 调用ai管理器 通过ai管理器 调用相应的doCast();
	 */
	//
	public void useMagic(L2Skill skill, boolean forceUse, boolean dontMove) {
		// 如果是被动技能不能使用
		if (skill.isPassive()) {
			// sendPacket(ActionFailed.STATIC_PACKET);
			return;
		}

		// 检查技能释放条件
		// 如技能 消耗的MP,HP等。
		if (!checkUseMagicConditions(skill, forceUse, dontMove)) {
			return;
		}

		// Check if the target is correct and Notify the AI with
		// AI_INTENTION_CAST and target
		L2Object target = null;

		switch (skill.getTargetType()) {
		// 如果 技能目标类型 是光环， 片伤， 自己， 那么即使没有目标也可以使用.
		// 以自己为目标
		case TARGET_GROUND:
		case TARGET_SELF:
		case TARGET_MULTIFACE:
			target = getTarget();
			break;
		default:

			// Get the first target of the list
			target = skill.getFirstOfTargetList(this);
			break;

		}

		if (target == null) {
			return;
		}

		getAI().setIntention(CtrlIntention.AI_INTENTION_CAST, skill, target);
	}

	private boolean checkUseMagicConditions(L2Skill skill, boolean forceUse, boolean dontMove) {

		if (isOutOfControl()) {
			// sendPacket(ActionFailed.STATIC_PACKET);
			return false;
		}

		// Check if the player is dead
		if (isDead()) {
			return false;
		}

		// ************************************* Check Target
		// *******************************************
		// Create and set a L2Object containing the target of the skill
		L2Object target = null;
		SkillTargetType sklTargetType = skill.getTargetType();
		Point2D worldPosition = getCurrentSkillWorldPosition();

		// 如果技能目标类型 是地面， 而没有地面坐标 那么不能释放技能
		if (sklTargetType == SkillTargetType.TARGET_GROUND && worldPosition == null) {
			return false;
		}

		switch (sklTargetType) {
		// Target the player if skill type is AURA, PARTY, CLAN or SELF
		case TARGET_PARTY:
		case TARGET_GROUND:
		case TARGET_SELF:
			target = this;
			break;
		case TARGET_PET:
		case TARGET_SUMMON:
			target = getPet();
			break;
		default:
			target = getTarget();
			break;
		}

		// 目标为空 那么不能释放技能
		if (target == null) {
			sendPacket(ActionFailed.STATIC_PACKET);
			return false;
		}

		// ************************************* Check skill availability
		// *******************************************

		// Check if this skill is enabled (ex : reuse time)
		// 技能是否在冷却中
		if (_skillCoolDown.isSkillCoolDown(skill)) {
			SystemMessage sm = null;
			// FastMap<Integer, TimeStamp> timeStamp = getReuseTimeStamp();
			TimeStamp timeStamp = _skillCoolDown.getSkillCoolTimeStamp(skill.getId());

			if (timeStamp != null) {
				int remainingTime = (int) (timeStamp.getRemaining() / 1000);
				int hours = remainingTime / 3600;
				int minutes = (remainingTime % 3600) / 60;
				int seconds = (remainingTime % 60);
				if (hours > 0) {
					sm = new SystemMessage(SystemMessageId.S2_HOURS_S3_MINUTES_S4_SECONDS_REMAINING_FOR_REUSE_S1);
					sm.addSkillName(skill);
					sm.addNumber(hours);
					sm.addNumber(minutes);
				} else if (minutes > 0) {
					sm = new SystemMessage(SystemMessageId.S2_MINUTES_S3_SECONDS_REMAINING_FOR_REUSE_S1);
					sm.addSkillName(skill);
					sm.addNumber(minutes);
				} else {
					sm = new SystemMessage(SystemMessageId.S2_SECONDS_REMAINING_FOR_REUSE_S1);
					sm.addSkillName(skill);
				}

				sm.addNumber(seconds);
			} else {
				sm = new SystemMessage(SystemMessageId.S1_PREPARED_FOR_REUSE);
				sm.addSkillName(skill);
			}

			sendPacket(sm);
			return false;

		}// end if ( _skillCoolDown.isSkillCoolDown( skill.getId() ) )

		// ************************************* Check casting conditions
		// *******************************************

		// Check if all casting conditions are completed
		// 检查技能的释放条件
		if (!skill.checkCondition(this, target, false)) {
			// Send a Server->Client packet ActionFailed to the L2PcInstance
			// sendPacket(ActionFailed.STATIC_PACKET);
			return false;
		}

		// ************************************* Check Skill Type
		// *******************************************

		// Check if this is offensive magic skill
		// 进攻型技能 需要判断 玩家是否在安全区中， 是否与目标的距离过远, 目标是否可攻击等
		if (skill.isOffensive()) {
			if ((isInsidePeaceZone(this, target)) && !getAccessLevel().allowPeaceAttack()) {
				// ActionFailed
				// 检查目标 是否在安全区域
				sendPacket(new SystemMessage(SystemMessageId.TARGET_IN_PEACEZONE));
				// sendPacket(ActionFailed.STATIC_PACKET);
				return false;
			}

			// Check if the target is attackable
			// 检查 目标是否可攻击的
			if (!target.isAttackable() && !getAccessLevel().allowPeaceAttack()) {
				// If target is not attackable, send a Server->Client packet
				// ActionFailed
				// sendPacket(ActionFailed.STATIC_PACKET);
				return false;
			}

			// Check if the target is in the skill cast range
			if (dontMove) {
				// 计算 和 目标的距离
				if (sklTargetType == SkillTargetType.TARGET_GROUND) {
					if (!isInsideRadius(getX(), getY(), skill.getCastRange())) {
						// 提示客户端 和 目标距离过远
						sendPacket(new SystemMessage(SystemMessageId.TARGET_TOO_FAR));

						// Send a Server->Client packet ActionFailed to the
						// L2PcInstance
						// sendPacket(ActionFailed.STATIC_PACKET);
						return false;
					}
				} else if (skill.getCastRange() > 0 && !isInsideRadius(target, skill.getCastRange())) {
					// Send a System Message to the caster
					sendPacket(new SystemMessage(SystemMessageId.TARGET_TOO_FAR));
					// Send a Server->Client packet ActionFailed to the
					// L2PcInstance
					// sendPacket(ActionFailed.STATIC_PACKET);
					return false;
				}

			}// end if (dontMove)

		}// end if (skill.isOffensive())

		if (skill.getCastRange() > 0) {
			if (sklTargetType == SkillTargetType.TARGET_GROUND) {
				if (!isInsideRadius(worldPosition.getX(), worldPosition.getY(), skill.getCastRange())) {
					sendPacket(new SystemMessage(SystemMessageId.CANT_SEE_TARGET));
					// sendPacket(ActionFailed.STATIC_PACKET);
					return false;
				}
			} else {
				if (!isInsideRadius(target, skill.getCastRange())) {
					sendPacket(new SystemMessage(SystemMessageId.CANT_SEE_TARGET));
					// sendPacket(ActionFailed.STATIC_PACKET);
					return false;
				}
			}

		}
		return true;

	} // end checkUseMagicConditions

	/**
	 * Check if the requested casting is a Pc->Pc skill cast and if it's a valid pvp condition
	 * 
	 * @param target
	 *            L2Object instance containing the target
	 * @param skill
	 *            L2Skill instance with the skill being casted
	 * @return False if the skill is a pvpSkill and target is not a valid pvp target
	 */
	public boolean checkPvpSkill(L2Object target, L2Skill skill) {
		return checkPvpSkill(target, skill, false);
	}

	/**
	 * Check if the requested casting is a Pc->Pc skill cast and if it's a valid pvp condition
	 * 
	 * @param target
	 *            L2Object instance containing the target
	 * @param skill
	 *            L2Skill instance with the skill being casted
	 * @param srcIsSummon
	 *            is L2Summon - caster?
	 * @return False if the skill is a pvpSkill and target is not a valid pvp target
	 */
	public boolean checkPvpSkill(L2Object target, L2Skill skill, boolean srcIsSummon) {
		// check for PC->PC Pvp status
		if (target != null && // target not null and
				target != this && // target is not self and
				target instanceof FuzePcInstance && !isInsideZone(ZONE_PVP) && // Pc
				// is
				// not
				// in
				// PvP
				// zone
				!((FuzePcInstance) target).isInsideZone(ZONE_PVP) // target is
		// not in
		// PvP zone
		) {
			if (skill.isPvpSkill()) // pvp skill
			{
				if (getClan() != null && ((FuzePcInstance) target).getClan() != null) {
					if (getClan().isAtWarWith(((FuzePcInstance) target).getClan().getClanId()) && ((FuzePcInstance) target).getClan().isAtWarWith(getClan().getClanId()))
						return true; // in clan war player can attack whites
					// even with sleep etc.
				}
				if (((FuzePcInstance) target).getPvpFlag() == 0 && // target's
						// pvp flag
						// is not
						// set and
						((FuzePcInstance) target).getKarma() == 0 // target has
				// no karma
				)
					return false;
			} else if ((getCurrentSkill() != null && !getCurrentSkill().isCtrlPressed() && skill.isOffensive() && !srcIsSummon) || (getCurrentPetSkill() != null && !getCurrentPetSkill().isCtrlPressed() && skill.isOffensive() && srcIsSummon)) {
				if (getClan() != null && ((FuzePcInstance) target).getClan() != null) {
					if (getClan().isAtWarWith(((FuzePcInstance) target).getClan().getClanId()) && ((FuzePcInstance) target).getClan().isAtWarWith(getClan().getClanId()))
						return true; // in clan war player can attack whites
					// even without ctrl
				}
				if (((FuzePcInstance) target).getPvpFlag() == 0 && // target's
						// pvp flag
						// is not
						// set and
						((FuzePcInstance) target).getKarma() == 0 // target has
				// no karma
				)
					return false;
			}
		}

		return true;
	}

	/**
	 * 是否是一个法师类职业.<BR>
	 * <BR>
	 */
	public boolean isMageClass() {
		return getClassId().isMage();
	}

	public boolean isMounted() {
		return _mountType > 0;
	}

	// returns false if the change of mount type fails.
	public boolean setMount(int npcId, int npcLevel, int mountType) {
		_mountNpcId = npcId;
		_mountLevel = npcLevel;
		_mountType = mountType;
		return true;
	}

	/**
	 * Return the type of Pet mounted (0 : none, 1 : Strider, 2 : Wyvern, 3: Wolf).<BR>
	 * <BR>
	 */
	public int getMountType() {
		return _mountType;
	}

	@Override
	public final void stopAllEffects() {
		super.stopAllEffects();
		updateAndBroadcastStatus(2);
	}

	@Override
	public final void stopAllEffectsExceptThoseThatLastThroughDeath() {
		super.stopAllEffectsExceptThoseThatLastThroughDeath();
		updateAndBroadcastStatus(2);
	}

	/**
	 * Send a Server->Client packet UserInfo to this L2PcInstance and CharInfo to all L2PcInstance in its _KnownPlayers.<BR>
	 * <BR>
	 * <B><U> Concept</U> :</B><BR>
	 * <BR>
	 * Others L2PcInstance in the detection area of the L2PcInstance are identified in <B>_knownPlayers</B>. In order to inform other players of this L2PcInstance state modifications, server just need to go through _knownPlayers to send Server->Client Packet<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Send a Server->Client packet UserInfo to this L2PcInstance (Public and Private Data)</li> <li>Send a Server->Client packet CharInfo to all L2PcInstance in _KnownPlayers of the L2PcInstance (Public data only)</li><BR>
	 * <BR>
	 * <FONT COLOR=#FF0000><B> <U>Caution</U> : DON'T SEND UserInfo packet to other players instead of CharInfo packet. Indeed, UserInfo packet contains PRIVATE DATA as MaxHP, STR, DEX...</B></FONT><BR>
	 * <BR>
	 */
	@Override
	public void updateAbnormalEffect() {
		// TODO:
		// 发送效果信息给客户端
		broadcastUserInfo();
	}

	@Override
	public String toString() {
		return "player " + getName();
	}

	/**
	 * Set the _lastFolkNpc of the L2PcInstance corresponding to the last Folk wich one the player talked.<BR>
	 * <BR>
	 */
	public void setLastFolkNPC(L2Npc folkNpc) {
		_lastFolkNpc = folkNpc;
	}

	/**
	 * Return the _lastFolkNpc of the L2PcInstance corresponding to the last Folk wich one the player talked.<BR>
	 * <BR>
	 */
	public L2Npc getLastFolkNPC() {
		return _lastFolkNpc;
	}

	/**
	 * 获取在家族中的特权等级
	 * 
	 * @param n
	 */
	public int getClanPrivileges() {
		return _clanPrivileges;
	}

	/**
	 * 设置在家族中的特权等级
	 * 
	 * @param n
	 */
	public void setClanPrivileges(int n) {
		_clanPrivileges = n;
	}

	public int getApprentice() {// 获得徒弟ID
		return _apprentice;
	}

	public void setApprentice(int apprentice_id) {
		_apprentice = apprentice_id;
	}

	public int getSponsor() {// 获得师傅的ID
		return _sponsor;
	}

	public void setSponsor(int sponsor_id) {
		_sponsor = sponsor_id;
	}

	@Override
	public void sendMessage(String message) {
		sendPacket(SystemMessage.sendString(message));
	}

	public void enterObserverMode(int x, int y) {

		setTarget(null);
		setIsParalyzed(true);
		setIsInvul(true);
		getAppearance().setInvisible();
		// sendPacket(new GMHide(1));
		// sendPacket(new ObservationMode(x, y));
		setXY(x, y);

		broadcastUserInfo();
	}

	public void leaveObserverMode() {
		setTarget(null);

		setIsParalyzed(false);
		// sendPacket(new GMHide(0));
		if (!AdminCommandAccessRights.getInstance().hasAccess("admin_invis", getAccessLevel()))
			getAppearance().setVisible();
		if (!AdminCommandAccessRights.getInstance().hasAccess("admin_invul", getAccessLevel()))
			setIsInvul(false);
		if (getAI() != null)
			getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);

		// sendPacket(new ObservationReturn(this));
		broadcastUserInfo();
	}

	public boolean getMessageRefusal() {// 是否消息拒绝
		return _messageRefusal;
	}

	public void setMessageRefusal(boolean mode) {
		_messageRefusal = mode;
		// sendPacket(new EtcStatusUpdate(this));
	}

	public void setTradeRefusal(boolean mode) {// 是否交易拒绝
		_tradeRefusal = mode;
	}

	public boolean getTradeRefusal() {
		return _tradeRefusal;
	}

	public BlockList getBlockList() {// 消息黑名单列表
		return _blockList;
	}

	public void sendSkillList() {
		// sendSkillList(this);
		sendPacket(new PcSkillTree(this));
	}

	public void sendSkillList(FuzePcInstance player) {
		// SkillList sl = new SkillList();
		// if (player != null) {
		// for (L2Skill s : player.getAllSkills()) {
		// if (s == null)
		// continue;
		// if (s.getId() > 9000 && s.getId() < 9007)
		// continue; // Fake skills to change base stats
		// if (_transformation != null &&
		// (!this.containsAllowedTransformSkill(s.getId()) &&
		// !s.allowOnTransform()))
		// continue;
		//
		// sl.addSkill(s.getId(), s.getLevel(), s.isPassive());
		// }
		// }
		// sendPacket(sl);

	}

	/**
	 * 玩家进入世界触发器
	 */
	public void onPlayerEnter() {

		//检查惩罚状态
		getPunish().updatePunishState();
		if (super.isInvul())
			sendMessage("以无敌的方式进入世界了.");
		if (getAppearance().getInvisible())
			sendMessage("以观察者的方式进入世界了.");
		if (getMessageRefusal())
			sendMessage("以禁言的方式进入世界了.");

		revalidateZone(true);
	}

	public long getLastAccess() {
		return _lastAccess;
	}

	public void set_lastAccess(long lastAccess) {
		_lastAccess = lastAccess;
	}

	/**
	 * 复活逻辑
	 */
	@Override
	public void doRevive() {
		super.doRevive();
		stopEffects(L2EffectType.CHARMOFCOURAGE);
		updateEffectIcons();
		// sendPacket(new EtcStatusUpdate(this));
		_reviveRequested = 0;

		if (isMounted())
			startFeed(_mountNpcId);
	}

	/**
	 * 由玩家死亡后所受到的技能或身上状态请求的复活调用
	 * 
	 * @param Reviver
	 * @param skill
	 * @param Pet
	 */
	public void reviveRequest(FuzePcInstance Reviver, L2Skill skill, boolean Pet) {
		if (_reviveRequested == 1) {
			if (_revivePet == Pet) {
				Reviver.sendPacket(new SystemMessage(SystemMessageId.RES_HAS_ALREADY_BEEN_PROPOSED)); // Resurrection
				// is
				// already
				// been
				// proposed.
			} else {
				if (Pet)
					Reviver.sendPacket(new SystemMessage(SystemMessageId.CANNOT_RES_PET2)); // A
				// pet
				// cannot
				// be
				// resurrected
				// while
				// it's
				// owner
				// is
				// in
				// the
				// process
				// of
				// resurrecting.
				else
					Reviver.sendPacket(new SystemMessage(SystemMessageId.MASTER_CANNOT_RES)); // While
				// a
				// pet
				// is
				// attempting
				// to
				// resurrect,
				// it cannot
				// help in
				// resurrecting
				// its
				// master.
			}
			return;
		}
		if ((Pet && getPet() != null && getPet().isDead()) || (!Pet && isDead())) {
			_reviveRequested = 1;
			_revivePet = Pet;

			// ConfirmDlg dlg = new
			// ConfirmDlg(SystemMessageId.RESSURECTION_REQUEST_BY_C1_FOR_S2_XP.getId());
			// dlg.addPcName(Reviver);
			// dlg.addString(String.valueOf(restoreExp));
			// sendPacket(dlg);
		}
	}

	/**
	 * 玩家对系统自动请求的复活调用的回复处理
	 * 
	 * @param answer
	 */
	public void reviveAnswer(int answer) {
		if (_reviveRequested != 1 || (!isDead() && !_revivePet) || (_revivePet && getPet() != null && !getPet().isDead()))
			return;
		// If character refuses a PhoenixBless autoress, cancel all buffs he had
		if (answer == 1) {
			if (!_revivePet) {
				doRevive();
			} else if (getPet() != null) {
				getPet().doRevive();
			}
		}
		_reviveRequested = 0;
	}

	public boolean isReviveRequested() {
		return (_reviveRequested == 1);
	}

	public boolean isRevivingPet() {
		return _revivePet;
	}

	public void removeReviving() {
		_reviveRequested = 0;
	}

	public void onActionRequest() {
		setProtection(false);
	}

	@Override
	public final void onTeleported(int id, int x, int y) {
		sendPacket(new TeleportToLocation(this, x, y));// 更新客户端坐标
		sendPacket(new SceneMap(id));// 更新客户端地图数据

		if ((Config.PLAYER_SPAWN_PROTECTION > 0))
			setProtection(true);

		// 驯化的野兽在场景跳转后消失
		if (getTrainedBeast() != null) {
			getTrainedBeast().decayMe();
			setTrainedBeast(null);
		}

		// 如果宠物存在传送宠物
		if (getPet() != null) {
			getPet().setFollowStatus(false);
			getPet().teleToLocation(id, getPosition().getX(), getPosition().getY());
			sendPacket(new TeleportToLocation(getPet(), x, y));// 更新宠物的坐标
			((L2SummonAI) getPet().getAI()).setStartFollowController(true);
			getPet().setFollowStatus(true);
			getPet().updateAndBroadcastStatus(0);
		}

		// 清除雷达上的所有标记
		getRadar().removeAllMarkers();

		// 通知客户端添加场景上其他的对象，通知场景上其他的对象添加客户端
		super.onTeleported(id, x, y);

		// 向玩家的雷达注册需要的对象
		for (L2Object obj : getScene().getVisibleObjects().values()) {
			getRadar().addMarker(obj);
		}
		
		getPosition().reset();

	}

	/**
	 * 减少当前对象的HP，覆盖了L2Character中的方法
	 */
	// Override
	public void reduceCurrentHp(int i, L2Character attacker, L2Skill skill) {
		getStatus().reduceHp(i, attacker);

		// 通知驯服的野兽发起攻击
		if (getTrainedBeast() != null)
			getTrainedBeast().onOwnerGotAttacked(attacker);
	}

	/**
	 * 减少当前对象的HP，覆盖了L2Character中的方法
	 */
	@Override
	public void reduceCurrentHp(int value, L2Character attacker, boolean awake, boolean isDOT, L2Skill skill) {
		getStatus().reduceHp(value, attacker, awake, isDOT, false);

		// 通知驯服的野兽发起攻击
		if (getTrainedBeast() != null)
			getTrainedBeast().onOwnerGotAttacked(attacker);
	}

	/**
	 * Manage the delete task of a L2PcInstance (Leave Party, Unsummon pet, Save its inventory in the database, Remove it from the world...).<BR>
	 * <BR>
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>If the L2PcInstance is in observer mode, set its position to its position before entering in observer mode</li> <li>Set the online Flag to True or False and update the characters table of the database with online status and lastAccess</li> <li>Stop the HP/MP/CP Regeneration task</li> <li>Cancel Crafting, Attak or Cast</li> <li>Remove the L2PcInstance from the world</li> <li>Stop Party and Unsummon Pet</li> <li>Update database with items in its inventory and remove them from the world</li> <li>
	 * Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI</li> <li>Close the connection with the client</li><BR>
	 * <BR>
	 */
	public void deleteMe() {
		// Set the online Flag to True or False
		setOnlineStatus(false);

		try {
			stopAllTimers();
		} catch (Exception e) {
			_log.error("deleteMe:(stopAllTimers)", getObjectId(), e);
		}

		try {
			setIsTeleporting(false);
		} catch (Exception e) {
			_log.error("deleteMe:(setIsTeleporting)", getObjectId(), e);
		}

		// Cancel Attak or Cast
		try {
			setTarget(null);
		} catch (Exception e) {
			_log.error("deleteMe:(setTarget)", getObjectId(), e);
		}

		try {
			for (L2Effect effect : getAllEffects()) {
				switch (effect.getEffectType()) {
				case SIGNET_GROUND:
				case SIGNET_EFFECT:
					effect.exit();
					break;
				}
			}
		} catch (Exception e) {
			_log.error("deleteMe:(getAllEffects)", getObjectId(), e);
		}

		// 删除雷达的对象
		if (getRadar() != null) {
			unRegisterNpcStateListener(getRadar());
			getRadar().removeAllMarkers();
		}

		// 从可见世界中删除此玩家，为了保证回写磁盘时有场景对象保存场景对象
		if (isVisible()) {
			try {
				decayMe();
			} catch (Exception e) {
				_log.error("deleteMe:(decayMe)", getObjectId(), e);
			}
		}

		// 如果在队伍中需要处理离线的一些情况
		if (isInParty()) {
			getParty().processLogout(this);
		}

		// If the L2PcInstance has Pet, unsummon it
		if (getPet() != null) {
			try {
				getPet().unSummon(this);
				// dead pet wasnt unsummoned, broadcast npcinfo changes (pet
				// will be without owner name - means owner offline)
				if (getPet() != null)
					getPet().broadcastNpcInfo(0);
			} catch (Exception e) {
				_log.error("deleteMe:(getPet)", getObjectId(), e);
			}// returns pet to control item
		}

		if (getClanId() != 0 && getClan() != null) {
			// set the status for pledge member list to OFFLINE
			try {
				L2ClanMember clanMember = getClan().getClanMember(getName());
				if (clanMember != null)
					clanMember.setPlayerInstance(null);

			} catch (Exception e) {
				_log.error("deleteMe:(getClanId)", getObjectId(), e);
			}
		}

		if (getActiveRequester() != null) {
			// deals with sudden exit in the middle of transaction
			setActiveRequester(null);
		}

		// If the L2PcInstance is a GM, remove it from the GM List
		if (isGM()) {
			try {
				GmListTable.getInstance().deleteGm(this);
			} catch (Exception e) {
				_log.error("deleteMe:(deleteGm)", getObjectId(), e);
			}
		}

		// remove player from instance and set spawn location if any
		try {
			final int instanceId = getInstanceId();
			if (instanceId != 0) {
				final Instance inst = InstanceManager.getInstance().getInstance(instanceId);
				if (inst != null) {
					inst.removePlayer(getObjectId());// 从副本中删除此玩家
					int[] spawn = inst.getSpawnLoc();
					getPosition().setScenePosition(spawn[0], spawn[1]);
					getPosition().setScene(FuzeWorld.getInstance().getScene(spawn[2]));
					if (getPet() != null) // dead pet
					{
						getPet().teleToLocation(spawn[2], spawn[0], spawn[1]);
						getPet().setInstanceId(0);
					}
				}
			}
		} catch (Exception e) {
			_log.error("deleteMe:(getInstanceId)", getObjectId(), e);
		}

		// Update database with items in its inventory and remove them from the
		// world
		try {
			getInventory().deleteMe();
		} catch (Exception e) {
			_log.error("deleteMe:(getInventory)", getObjectId(), e);
		}

		// Update database with items in its warehouse and remove them from the
		// world
		try {
			clearWarehouse();
		} catch (Exception e) {
			_log.error("deleteMe:(clearWarehouse)", getObjectId(), e);
		}

		// Update database with items in its freight and remove them from the
		// world
		try {
			clearFreight();
		} catch (Exception e) {
			_log.error("deleteMe:(clearFreight)", getObjectId(), e);
		}

		try {
			clearDepositedFreight();
		} catch (Exception e) {
			_log.error("deleteMe:(clearDepositedFreight)", getObjectId(), e);
		}

		// if (getClanId() > 0)
		// getClan().broadcastToOtherOnlineMembers(new
		// PledgeShowMemberListUpdate(this), this);

		// 清除监听者
		if (_snoopListener != null) {
			for (FuzePcInstance player : _snoopListener)
				player.removeSnooped(this);
		}

		if (_chanceSkills != null) {
			_chanceSkills.setOwner(null);
			_chanceSkills = null;
		}
		ConsignmentManager.removeShelveItemListener(this.getObjectId());
		ConsignmentManager.removeSearcheCondition(this.getObjectId());

		FuzeWorld.getInstance().exitWorld(this);
		_log.info("角色下线:", getObjectId(), getName());
	}

	public int getInventoryLimit() {
		return _inventory.getInventoryLimit();
	}

	public int getWareHouseLimit() {
		int whlim;
		whlim = Config.WAREHOUSE_SLOTS_NO_DWARF;

		return whlim;
	}

	/**
	 * @return Returns the mountNpcId.
	 */
	public int getMountNpcId() {
		return _mountNpcId;
	}

	/**
	 * @return Returns the mountLevel.
	 */
	public int getMountLevel() {
		return _mountLevel;
	}

	public void setMountObjectID(long newID) {
		_mountObjectID = newID;
	}

	public long getMountObjectID() {
		return _mountObjectID;
	}

	/**
	 * Get the current skill in use or return null.<BR>
	 * <BR>
	 */
	public SkillDat getCurrentSkill() {
		return _currentSkill;
	}

	/**
	 * Create a new SkillDat object and set the player _currentSkill.<BR>
	 * <BR>
	 */
	public void setCurrentSkill(L2Skill currentSkill, boolean ctrlPressed, boolean shiftPressed) {
		if (currentSkill == null) {
			if (_log.isDebugEnabled())
				_log.debug("Setting current skill: NULL for " + getName() + ".", Config.SERVER_ID, getName());

			_currentSkill = null;
			return;
		}

		if (_log.isDebugEnabled())
			_log.debug("Setting current skill: " + currentSkill.getName() + " (ID: " + currentSkill.getId() + ") for " + getName() + ".", Config.SERVER_ID, getName());

		_currentSkill = new SkillDat(currentSkill, ctrlPressed, shiftPressed);

	}

	/**
	 * Get the current pet skill in use or return null.<br>
	 * <br>
	 */
	public SkillDat getCurrentPetSkill() {
		return _currentPetSkill;
	}

	/**
	 * Create a new SkillDat object and set the player _currentPetSkill.<br>
	 * <br>
	 */
	public void setCurrentPetSkill(L2Skill currentSkill, boolean ctrlPressed, boolean shiftPressed) {
		if (currentSkill == null) {
			if (_log.isDebugEnabled())
				_log.debug("Setting current pet skill: NULL for " + getName() + ".", Config.SERVER_ID, getName());

			_currentPetSkill = null;
			return;
		}

		if (_log.isDebugEnabled())
			_log.debug("Setting current Pet skill: " + currentSkill.getName() + " (ID: " + currentSkill.getId() + ") for " + getName() + ".", Config.SERVER_ID, getName());

		_currentPetSkill = new SkillDat(currentSkill, ctrlPressed, shiftPressed);
	}

	public SkillDat getQueuedSkill() {
		return _queuedSkill;
	}

	/**
	 * Create a new SkillDat object and queue it in the player _queuedSkill.<BR>
	 * <BR>
	 */
	/***
	 * 创建一个排队技能， 当这个被创建时 说明当前有技能在释放
	 */
	public void setQueuedSkill(L2Skill queuedSkill, boolean ctrlPressed, boolean shiftPressed) {
		if (queuedSkill == null) {
			if (_log.isDebugEnabled())
				_log.debug("Setting queued skill: NULL for " + getName() + ".", Config.SERVER_ID, getName());

			_queuedSkill = null;
			return;
		}

		if (_log.isDebugEnabled())
			_log.debug("Setting queued skill: " + queuedSkill.getName() + " (ID: " + queuedSkill.getId() + ") for " + getName() + ".", Config.SERVER_ID, getName());

		// 技能释放信息
		_queuedSkill = new SkillDat(queuedSkill, ctrlPressed, shiftPressed);
	}

	/**
	 * 设置玩家的惩罚等级
	 * 
	 * @param state
	 * @param time
	 */
	public void setPunishLevel(int state, long time) {
		_punish.setPunishTimer(time);
		_punish.setPunishLevel(state);
	}

	public Punish getPunish() {
		return _punish;
	}

	private boolean _canFeed;

	/**
	 * Simple class containing all neccessary information to maintain valid timestamps and reuse for skills upon relog. Filter this carefully as it becomes redundant to store reuse for small delays.
	 * 
	 * @author Yesod
	 */
	// public static class TimeStamp {
	// private int skill;
	//
	// private long reuse;
	//
	// private long stamp;
	//
	// public TimeStamp(int _skill, long _reuse) {
	// skill = _skill;
	// reuse = _reuse;
	// stamp = System.currentTimeMillis() + reuse;
	// }
	//
	// public TimeStamp(int _skill, long _reuse, long _systime) {
	// skill = _skill;
	// reuse = _reuse;
	// stamp = _systime;
	// }
	//
	// public long getStamp() {
	// return stamp;
	// }
	//
	// public int getSkill() {
	// return skill;
	// }
	//
	// public long getReuse() {
	// return reuse;
	// }
	//
	// public long getRemaining() {
	// return Math.max(stamp - System.currentTimeMillis(), 0);
	// }
	//
	// /*
	// * Check if the reuse delay has passed and if it has not then update the
	// * stored reuse time according to what is currently remaining on the
	// * delay.
	// */
	// public boolean hasNotPassed() {
	// if (System.currentTimeMillis() < stamp) {
	// return true;
	// }
	// return false;
	// }
	// }

	/**
	 * 把技能加入冷却管理系统中 sk : 技能 itemId : 物品id 如果技能是由物品触发的话 reuse : 技能在使用时间 (技能冷却时间)
	 */
	@Override
	public void addTimeStamp(L2Skill sk, int itemId, int reuse) {
		_skillCoolDown.addSkillCoolDown(sk, itemId, reuse);
	}

	/**
	 * 把技能加入冷却管理系统中 sk : 技能 itemId : 物品id 如果技能是由物品触发的话 使用物品时 调用次接口
	 */
	@Override
	public void addTimeStamp(L2Skill sk, int itemId) {
		_skillCoolDown.addSkillCoolDown(sk, itemId);
	}

	/**
	 * 数据库恢复 技能 冷却时间 除了数据库恢复之外，其他不应该调用这个函数 去增加技能冷却时间
	 * 
	 * @param sk
	 *            : 技能
	 * @param itemId
	 *            :物品id
	 * @param reuse
	 *            ： 技能冷却时间
	 * @param catcool
	 *            : 技能类型冷却时间
	 */
	public void addTimeStamp(int skid, int itemId, int reuse, int catcool) {
		_skillCoolDown.addSkillCoolDown(skid, itemId, reuse, catcool);
	}

	/**
	 * 获得角色身上的 冷却管理器
	 * 
	 * @return
	 */
	public FuzeSkillCoolDown getSkillCoolList() {
		return _skillCoolDown;
	}

	/**
	 * Index according to skill id the current timestamp of use.
	 * 
	 * @param skillid
	 */
	@Override
	public void removeTimeStamp(int s) {
		_skillCoolDown.removeSkillCoolTime(s);
	}

	@Override
	public FuzePcInstance getActingPlayer() {
		return this;
	}

	/*
	 * Function for skill summon friend or Gate Chant.
	 */
	/** Request Teleport **/
	public boolean teleportRequest(FuzePcInstance requester, L2Skill skill) {
		if (_summonRequest.getTarget() != null && requester != null)
			return false;
		_summonRequest.setTarget(requester, skill);
		return true;
	}

	/** Action teleport **/
	public void teleportAnswer(int answer, int requesterId) {
		if (_summonRequest.getTarget() == null)
			return;
		// if (answer == 1 && _summonRequest.getTarget().getCharId() ==
		// requesterId) {
		// teleToTarget(this, _summonRequest.getTarget(),
		// _summonRequest.getSkill());
		// }
		_summonRequest.setTarget(null, null);
	}

	public void teleToTarget(FuzePcInstance targetChar, FuzePcInstance summonerChar, L2Skill summonSkill) {
		if (targetChar == null || summonerChar == null || summonSkill == null)
			return;

		if (!checkSummonerStatus(summonerChar))
			return;
		if (!checkTargetStatus(targetChar, summonerChar))
			return;

		// TODO : 需要修改
		// int[] itemConsumeId = summonSkill.getTargetConsumeId();
		// int[] itemConsumeCount = summonSkill.getTargetConsume();
		// if (itemConsumeId != 0 && itemConsumeCount != 0) {
		// //Delete by rocknow
		// if (targetChar.getInventory().getInventoryItemCount(itemConsumeId, 0)
		// < itemConsumeCount) {
		// SystemMessage sm = new
		// SystemMessage(SystemMessageId.S1_REQUIRED_FOR_SUMMONING);
		// sm.addItemName(summonSkill.getTargetConsumeId());
		// targetChar.sendPacket(sm);
		// return;
		// }
		// targetChar.getInventory().destroyItemByItemId("Consume",
		// itemConsumeId, itemConsumeCount, summonerChar, targetChar);
		// SystemMessage sm = new SystemMessage(SystemMessageId.S1_DISAPPEARED);
		// sm.addItemName(summonSkill.getTargetConsumeId());
		// targetChar.sendPacket(sm);
		// }
		// targetChar.teleToLocation(summonerChar.getX(), summonerChar.getY(),
		// summonerChar.getZ(), true);
	}

	public static boolean checkSummonerStatus(FuzePcInstance summonerChar) {
		if (summonerChar == null)
			return false;

		if (summonerChar.isInsideZone(L2Character.ZONE_NOSUMMONFRIEND)) {
			summonerChar.sendPacket(new SystemMessage(SystemMessageId.YOUR_TARGET_IS_IN_AN_AREA_WHICH_BLOCKS_SUMMONING));
			return false;
		}
		return true;
	}

	public static boolean checkTargetStatus(FuzePcInstance targetChar, FuzePcInstance summonerChar) {
		if (targetChar == null)
			return false;

		if (targetChar.isDead()) {
			SystemMessage sm = new SystemMessage(SystemMessageId.C1_IS_DEAD_AT_THE_MOMENT_AND_CANNOT_BE_SUMMONED);
			sm.addPcName(targetChar);
			summonerChar.sendPacket(sm);
			return false;
		}

		if (targetChar.isRooted() || targetChar.isInCombat()) {
			SystemMessage sm = new SystemMessage(SystemMessageId.C1_IS_ENGAGED_IN_COMBAT_AND_CANNOT_BE_SUMMONED);
			sm.addPcName(targetChar);
			summonerChar.sendPacket(sm);
			return false;
		}

		if (targetChar.isInsideZone(L2Character.ZONE_NOSUMMONFRIEND)) {
			SystemMessage sm = new SystemMessage(SystemMessageId.C1_IN_SUMMON_BLOCKING_AREA);
			sm.addString(targetChar.getName());
			summonerChar.sendPacket(sm);
			return false;
		}

		return true;
	}

	/**
	 * 检查道具的限制情况(等级不符合装备的上下限，卸除装备)
	 */
	public void checkItemRestriction() {
		for (int i = 0; i < Inventory.PAPERDOLL_TOTALSLOTS; i++) {
			L2ItemInstance equippedItem = getInventory().getPaperdollItem(i);
			if (equippedItem != null && !equippedItem.getItem().checkCondition(this, this, false)) {
				getInventory().unEquipItemInSlotAndRecord(i);
				if (equippedItem.isWear())
					continue;

				SystemMessage sm = null;

				sm = new SystemMessage(SystemMessageId.S1_DISARMED);
				sm.addItemName(equippedItem);

				sendPacket(sm);
			}
		}
	}

	public void setTransformAllowedSkills(int[] ids) {
		_transformAllowedSkills = ids;
	}

	public boolean containsAllowedTransformSkill(int id) {
		for (int i = 0; i < _transformAllowedSkills.length; i++) {
			if (_transformAllowedSkills[i] == id) {
				return true;
			}
		}
		return false;
	}

	/*------------------------------------宠物喂养部分------------------------------------------*/

	protected void startFeed(int npcId) {
		_canFeed = npcId > 0;
		if (!isMounted())
			return;
		// if (getPet() != null) {
		// setCurrentFeed(((L2PetInstance) getPet()).getCurrentFed());
		// _controlItemId = getPet().getControlItemId();
		// sendPacket(new SetupGauge(3, getCurrentFeed() * 10000 /
		// getFeedConsume(), getMaxFeed() * 10000 / getFeedConsume()));
		// if (!isDead()) {
		// _mountFeedTask = new Timer(100000,new FeedTask());
		// _mountFeedTask.start();
		// }
		// } else if (_canFeed) {
		// setCurrentFeed(getMaxFeed());
		// SetupGauge sg = new SetupGauge(3, getCurrentFeed() * 10000 /
		// getFeedConsume(), getMaxFeed() * 10000 / getFeedConsume());
		// sendPacket(sg);
		// if (!isDead()) {
		// _mountFeedTask = new Timer(100000,new FeedTask());
		// _mountFeedTask.start();
		// }
		// }
	}

	protected void stopFeed() {
		if (_mountFeedTask != null) {
			_mountFeedTask.cancel();
			_mountFeedTask = null;
			if (_log.isDebugEnabled())
				_log.debug("Pet [#" + _mountNpcId + "] feed task stop", Config.SERVER_ID, "停止喂养");
		}
	}

	/** 宠物的喂养任务 */
	class FeedTask implements Runnable {
		public void run() {
			try {
				if (!isMounted()) {
					stopFeed();
					return;
				}

				if (getCurrentFeed() > getFeedConsume()) {
					// eat
					setCurrentFeed(getCurrentFeed() - getFeedConsume());
				} else {
					// go back to pet control item, or simply said, unsummon it
					setCurrentFeed(0);
					stopFeed();
					dismount();
					sendPacket(new SystemMessage(SystemMessageId.OUT_OF_FEED_MOUNT_CANCELED));
				}

				int[] foodIds = L2PetDataTable.getFoodItemId(getMountNpcId());
				if (foodIds[0] == 0)
					return;
				L2ItemInstance food = null;
				food = getInventory().getItemByItemId(foodIds[0]);

				// use better strider food if exists
				if (L2PetDataTable.isStrider(getMountNpcId())) {
					if (getInventory().getItemByItemId(foodIds[1]) != null)
						food = getInventory().getItemByItemId(foodIds[1]);
				}
				if (food != null && isHungry()) {
					IItemHandler handler = ItemHandler.getInstance().getItemHandler(food.getEtcItem());
					if (handler != null) {
						handler.useItem(FuzePcInstance.this, food);
						SystemMessage sm = new SystemMessage(SystemMessageId.PET_TOOK_S1_BECAUSE_HE_WAS_HUNGRY);
						// sm.addItemName(food.getItemId());
						sendPacket(sm);
					}
				}
			} catch (Exception e) {
				_log.error("Mounted Pet [NpcId: " + getMountNpcId() + "] a feed task error has occurred", getMountNpcId(), e);
			}
		}
	}

	protected final void clearPetData() {
		_data = null;
	}

	protected final L2PetData getPetData(int npcId) {
		if (_data == null && getPet() != null)
			_data = L2PetDataTable.getInstance().getPetData(getPet().getNpcId(), getPet().getLevel());
		else if (_data == null && npcId > 0) {
			_data = L2PetDataTable.getInstance().getPetData(npcId, getLevel());
		}

		return _data;
	}

	public int getCurrentFeed() {
		return _curFeed;
	}

	protected int getFeedConsume() {
		// if pet is attacking
		if (isAttackingNow())
			return getPetData(_mountNpcId).getPetFeedBattle();
		else
			return getPetData(_mountNpcId).getPetFeedNormal();
	}

	public void setCurrentFeed(int num) {
		_curFeed = num > getMaxFeed() ? getMaxFeed() : num;
		// SetupGauge sg = new SetupGauge(3, getCurrentFeed() * 10000 /
		// getFeedConsume(), getMaxFeed() * 10000 / getFeedConsume());
		// sendPacket(sg);
	}

	protected int getMaxFeed() {
		return getPetData(_mountNpcId).getPetMaxFeed();
	}

	protected boolean isHungry() {
		return _canFeed ? (getCurrentFeed() < (0.55 * getPetData(getMountNpcId()).getPetMaxFeed())) : false;
	}

	// public void storePetFood() {
	// if (_controlItemId != 0 && _mountNpcId != 0) {
	// String req;
	// req = "UPDATE pets SET fed=? WHERE item_obj_id = ?";
	// Connection con = null;
	// try {
	// con = L2DatabaseFactory.getInstance().getConnection();
	// PreparedStatement statement = con.prepareStatement(req);
	// statement.setInt(1, getCurrentFeed());
	// statement.setInt(2, _controlItemId);
	// statement.executeUpdate();
	// statement.close();
	// _controlItemId = 0;
	// } catch (Exception e) {
	// _log.error("Failed to store Pet [NpcId: " + _mountNpcId + "] data", e);
	// } finally {
	// try {
	// con.close();
	// } catch (Exception e) {
	// }
	// }
	// }
	// }

	public FloodProtectors getFloodProtectors() {
		return _floodProtectors;
	}

	/**
	 * 检测是否处于队伍中，队伍中的可以抢物品
	 * 
	 * @param LooterId
	 * @return
	 */
	public boolean isInLooterParty(long LooterId) {
		FuzePcInstance looter = (FuzePcInstance) FuzeWorld.getInstance().findObject(LooterId);

		// if L2PcInstance is in a CommandChannel
		if (isInParty() && getParty().isInCommandChannel() && looter != null)
			return getParty().getCommandChannel().getMembers().contains(looter);

		if (isInParty() && looter != null)
			return getParty().getPartyMembers().contains(looter);

		return false;
	}

	/**
	 * 发送此玩家的数据给指定的玩家
	 */
	@Override
	public void sendInfo(FuzePcInstance activeChar) {
		activeChar.sendPacket(new CharInfo(this));
		// activeChar.sendPacket(new ExBrExtraUserInfo(this));
		//
		// if (getMountType() == 4) {
		// // TODO: Remove when horse mounts fixed
		// activeChar.sendPacket(new Ride(this, false, 0));
		// activeChar.sendPacket(new Ride(this, true, getMountNpcId()));
		// }
	}

	public final static float EXPADD_RADIO = 0.4f;

	@Override
	public void addExp(int addToExp) {
		getStat().addExp(addToExp);
		getInventory().notifyStoreExp(addToExp);
	}

	/**
	 * 给监听当前玩家消息的GM发送监听信息
	 * 
	 * @param type
	 * @param name
	 * @param _text
	 */
	public void broadcastSnoop(int type, String name, String _text) {
		if (_snoopListener == null)
			return;
		if (!_snoopListener.isEmpty()) {
			// Snoop sn = new Snoop(getObjectId(), getName(), type, name,
			// _text);
			//
			// for (L2PcInstance pci : _snoopListener)
			// if (pci != null)
			// pci.sendPacket(sn);
		}
	}

	/**
	 * 把一个GM的连接加入到监听列表中
	 * 
	 * @param pci
	 */
	public void addSnooper(FuzePcInstance pci) {
		if (_snoopListener == null)
			_snoopListener = new FastList<FuzePcInstance>();
		if (!_snoopListener.contains(pci))
			_snoopListener.add(pci);
	}

	/**
	 * 把一个GM的连接从监听列表中删除
	 * 
	 * @param pci
	 */
	public void removeSnooper(FuzePcInstance pci) {
		_snoopListener.remove(pci);
	}

	/**
	 * 把一个监听对象加入到被被监听列表中
	 * 
	 * @param pci
	 */
	public void addSnooped(FuzePcInstance pci) {
		if (_snoopedPlayer == null)
			_snoopedPlayer = new FastList<FuzePcInstance>();
		if (!_snoopedPlayer.contains(pci))
			_snoopedPlayer.add(pci);
	}

	public void removeSnooped(FuzePcInstance pci) {
		_snoopedPlayer.remove(pci);
	}

	/**
	 * 返回玩家的职业对象.<BR>
	 * <BR>
	 */
	public ClassId getClassId() {
		return ClassId.getClassId(getTemplate().classId);
	}

	/**
	 * 设置玩家的仙魔位的等级
	 * 
	 * @param id
	 */
	public void setPracticeId(int id) {
		_practice = PracticeId.getPractice(id);
	}

	/**
	 * 返回玩家的仙魔位枚举
	 * 
	 * @return
	 */
	public PracticeId getPracticeId() {
		return _practice;
	}

	/**
	 * 设置激活新的仙魔位
	 * 
	 * @param id
	 */
	public void rewardPractice() {
		if (_practice.canPracticeLevelUp(this)) {
			checkItemRestriction();
		}
	}

	/**
	 * 获得玩家的种族
	 * 
	 * @return
	 */
	public Race getRace() {
		return getClassId().getRace();
	}

	public int getNextLevelNeedExperience() {
		return getStat().getNextLevelNeedExperience();
	}

	public Set<String> getEventQuests(Quest.QuestEventType EventType) {
		if (_questEvents == null) {
			return null;
		}
		return _questEvents.get(EventType);
	}

	public Map<QuestEventType, Set<String>> getQuestEvents() {
		return _questEvents;
	}

	/**
	 * 删除任务事件
	 * 
	 * @param EventType
	 * @param q
	 *            2010-4-27
	 * @author lyh
	 */
	public void removeQuestEvents(Quest.QuestEventType EventType, Quest q) {
		if (_questEvents == null)
			return;
		if (_questEvents.get(EventType) == null) {
			return;
		} else {
			Set<String> _quests = _questEvents.get(EventType);
			for (Iterator<String> itr = _quests.iterator(); itr.hasNext();) {
				String questN = itr.next();
				if (questN.equals(q.getName()))
					itr.remove();
			}
		}
	}

	/**
	 * 添加任务事件
	 * 
	 * @param EventType
	 * @param q
	 *            2010-4-27
	 * @author lyh
	 */
	public void addQuestEvent(Quest.QuestEventType EventType, Quest q) {
		if (_questEvents == null)
			_questEvents = new FastMap<Quest.QuestEventType, Set<String>>();

		if (_questEvents.get(EventType) == null) {
			Set<String> s = new HashSet<String>();
			s.add(q.getName());
			_questEvents.put(EventType, s);
		} else {
			Set<String> s = _questEvents.get(EventType);

			if (!EventType.isMultipleRegistrationAllowed()) {// 是否允许多个注册
				s.clear();
				s.add(q.getName());
			} else {
				s.add(q.getName());
			}
		}
	}

	/**
	 * 通知包含使用技能的任务逻辑
	 * 
	 * @param skill
	 *            2010-4-27
	 * @author lyh
	 */
	public void notifyQuestEventUseSkill(L2Skill skill) {
		try {
			if (this.getEventQuests(Quest.QuestEventType.ON_USER_SKILL) != null) {
				for (String name : this.getEventQuests(Quest.QuestEventType.ON_USER_SKILL)) {
					Quest quest = QuestManager.getInstance().getQuest(name);
					if (quest != null)
						quest.notifyUseSkill(this, skill);
					else
						_log.warn(getName() + "'s quest is null:" + name, getObjectId(), getName());
				}
			}
		} catch (Exception e) {
			_log.error("FuzePcInstance.notifyQuestEventUseSkill error", getObjectId(), e);
		}
	}

	/**
	 * 通知包含使用技能的任务逻辑
	 * 
	 * @param skill
	 *            2010-4-27
	 * @author lyh
	 */
	public void notifyQuestEventAddItem(L2ItemInstance item) {
		try {
			if (this.getEventQuests(Quest.QuestEventType.ON_USER_ADDITEM) != null) {
				for (String name : this.getEventQuests(Quest.QuestEventType.ON_USER_ADDITEM)) {
					Quest quest = QuestManager.getInstance().getQuest(name);
					if (quest != null)
						quest.notifyAddItem(this, item);
					else
						_log.warn(getName() + "'s quest is null:" + name, getObjectId(), getName());
				}
			}
		} catch (Exception e) {
			_log.error("FuzePcInstance.notifyQuestEventAddItem error", getObjectId(), e);
		}
	}

	/**
	 * 玩家任务数据
	 * 
	 * @author lyh
	 */
	public static class PlayerQuestValues {
		/**
		 * 任务名称
		 */
		private String name;

		/**
		 * 键
		 */
		private String val;

		/**
		 * 值
		 */
		private String value;

		public PlayerQuestValues(String name, String val, String value) {
			this.name = name;
			this.val = val;
			this.value = value;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getVal() {
			return val;
		}

		public void setVal(String val) {
			this.val = val;
		}

		public String getValue() {
			return value;
		}

		public void setValue(String value) {
			this.value = value;
		}

	}

	/**
	 * 任务数据
	 * 
	 * @param name
	 *            任务名称
	 * @param val
	 *            键
	 * @param value
	 *            值
	 * @return 2010-5-13
	 * @author lyh
	 */
	public PlayerQuestValues newPlayerQuestValues(String name, String val, String value) {
		return new PlayerQuestValues(name, val, value);
	}

	/**
	 * 获取任务数据
	 * 
	 * @return 2010-4-28
	 * @author lyh
	 */
	public List<PlayerQuestValues> getQuestValues() {
		return _questValues;
	}

	/**
	 * 设置任务数据
	 * 
	 * @param questValues
	 *            2010-4-28
	 * @author lyh
	 */
	public void setQuestValues(List<PlayerQuestValues> questValues) {
		_questValues = questValues;
	}

	/**
	 * 刷新可接任务列表 2010-5-4
	 * 
	 * @author lyh
	 */
	public void refreshMayQuestList() {
		Iterable<Quest> questList = QuestManager.getInstance().getAllManagedScripts();
		for (Quest q : questList) {
			if (q.getQuestDataSet().getNeedPlayerLv() <= this.getLevel() && ((q.getQuestDataSet().getNeedRace() != null && q.getQuestDataSet().getNeedRace().getId() == this.getRace().getId()) || (q.getQuestDataSet().getNeedRace() == null))) {// 等级过滤
				int preQuestId = q.getQuestDataSet().getPreQuestId();// 前置任务id
				String questName = q.getName();

				for (Iterator<String> itr = _accepyQuestList.iterator(); itr.hasNext();) {
					String quest = itr.next();
					QuestState qs = this.getQuestState(quest);
					if (qs != null && qs.getQuestName().equals(questName)) {// 过滤已经任务
						continue;
					}
				}

				if (preQuestId == -1) {// 等级条件符合,无前置任务要求,进入可接列表
					this._mayAccepyQuestList.add(questName);
				} else {
					Quest preQuest = QuestManager.getInstance().getQuest(preQuestId);
					if (preQuest == null)
						_log.warn("Quest id: " + q.getQuestIntId() + ",preQuestId is null:" + preQuestId, getObjectId(), q.getName());
					QuestState qs = this.getQuestState(preQuest.getName());
					if (qs != null) {
						if (qs.getState() == State.COMPLETED)// 前置任务已经完成,进入可接列表
							this._mayAccepyQuestList.add(questName);
					}
				}
			}
		}

		for (Iterator<String> itr = _mayAccepyQuestList.iterator(); itr.hasNext();) {// 过滤未接任务列表中已经完成的任务
			String quest = itr.next();
			QuestState qs = this.getQuestState(quest);
			if (qs != null) {
				if (qs.getState() == State.COMPLETED)
					itr.remove();
			}
		}

	}

	/**
	 * 清除可接任务列表(如:接受任务时)
	 * 
	 * @param quest
	 *            2010-5-10
	 * @author lyh
	 */
	public void removeMayQuestList(String quest) {
		if (QuestManager.getInstance().getQuest(quest) == null)
			_log.warn("Quest (name='" + quest + "') not found.by FuzePcInstance.removeMayQuestList", getObjectId(), getName());
		for (Iterator<String> itr = _mayAccepyQuestList.iterator(); itr.hasNext();) {
			String q = itr.next();
			if (q.equals(quest)) {
				itr.remove();
			}
		}
	}

	public Set<String> getMayAccepyQuestList() {
		return this._mayAccepyQuestList;
	}

	public long getLastChatTime() {
		return this._lastChatTime;
	}

	public void setLastChatTime(long lastChatTime) {
		this._lastChatTime = lastChatTime;
	}

	/**
	 * 刷新已经任务列表 2010-5-4
	 * 
	 * @author lyh
	 */
	public void refreshQuestList() {
		for (Entry<String, QuestState> entry : _quests.entrySet()) {
			QuestState qs = entry.getValue();
			if (qs.getState() >= State.STARTED && qs.getState() < State.COMPLETED) {// 过滤已经任务
				_accepyQuestList.add(qs.getQuestName());
			}
		}
	}

	/**
	 * 清除已接任务(如:放弃(完成)任务时刷新)
	 * 
	 * @param quest
	 *            2010-5-10
	 * @author lyh
	 */
	public void removeQuestList(String quest) {
		if (QuestManager.getInstance().getQuest(quest) == null)
			_log.warn("Quest (name='" + quest + "') not found.by FuzePcInstance.removeQuestList", getObjectId(), getName());
		for (Iterator<String> itr = _accepyQuestList.iterator(); itr.hasNext();) {
			String qs = itr.next();
			if (qs.equals(quest))
				itr.remove();
		}
	}

	public Set<String> getAccepyQuestList() {
		return this._accepyQuestList;
	}

	/**
	 * 玩家任务列表 2010-5-7
	 * 
	 * @author lyh
	 */
	public String playerQuestList() {
		String content = HtmCache.getInstance().getHtm("data/xml/windows/playerQuestList.xml");
		if (content == null) {
			_log.warn("playerQuestList xml is null", Config.SERVER_ID, "玩家任务列表");
			return "";
		}

		StringBuilder str = new StringBuilder();
		String temp;
		for (Iterator<String> itr = _accepyQuestList.iterator(); itr.hasNext();) {
			temp = "<tr><td><a pl='min' nm='%bypass%' cmd='' tip='%questInfoTalk%' oc='yjcz(\"%bypass%\")'>%msg%</a></td></tr>";
			String quest = itr.next();
			QuestState qs = this.getQuestState(quest);
			if (qs == null) {
				_log.warn("FuzePcInstance.playerQuestList _accepyQuestList Quest:" + quest + ", is null", getObjectId(), quest);
				continue;
			}
			QuestDataSet qds = qs.getQuest().getQuestDataSet();
			temp = temp.replaceAll("%questInfoTalk%", qds.getQuestInfo());
			temp = temp.replaceAll("%bypass%", qs.getQuestName());
			String diff = QuestDataSet.QuestDifficulty.getQuestDifficulty(qds.getQuestDifficulty()).getName();
			if ("困难".equals(diff)) {
				temp = temp.replaceAll("%msg%", "【" + QuestDataSet.QuestClass.getQuestClass(qds.getQuestClass() - 1).getName() + "】" + qds.getName() + "[" + diff + "](" + State.getStateName_CN(qs.getState()) + ")");// [主]任务A(进行中)
			} else {
				temp = temp.replaceAll("%msg%", "【" + QuestDataSet.QuestClass.getQuestClass(qds.getQuestClass() - 1).getName() + "】" + qds.getName() + "(" + State.getStateName_CN(qs.getState()) + ")");// [主]任务A(进行中)
			}

			str.append(temp);
		}
		content = content.replaceAll("%yjrw%", str.toString());// 填充已经任务
		str.setLength(0);
		for (Iterator<String> itr = _mayAccepyQuestList.iterator(); itr.hasNext();) {

			temp = "<tr><td><a pl='min' nm='%bypass%' cmd='' tip='%taskBriefing%' oc='wjcz(\"%bypass%\")'>%msg%</a></td></tr>";
			String quest = itr.next();

			if (_accepyQuestList.contains(quest)) {
				continue;
			}

			Quest q = QuestManager.getInstance().getQuest(quest);
			if (q == null) {
				_log.warn("FuzePcInstance.playerQuestList _mayAccepyQuestList Quest:" + quest + ", is null", getObjectId(), getName());
				continue;
			}
			QuestDataSet qds = q.getQuestDataSet();
			temp = temp.replaceAll("%taskBriefing%", qds.getTaskBriefing() == null ? "" : qds.getTaskBriefing());
			temp = temp.replaceAll("%bypass%", q.getName());
			temp = temp.replaceAll("%msg%", qds.getName());
			str.append(temp);
		}
		content = content.replaceAll("%wjrw%", str.toString());
		content = content.replaceAll("%hd%", "暂时没有活动开放!");
		return content;
	}

	/**
	 * 获取npc对玩家任务表情
	 * 
	 * @param npc
	 * @return 2010-5-11
	 * @author lyh
	 */
	// public int getNpcQuestFace(L2Npc npc) {
	// if (npc != null) {
	// NpcTemplate npct = npc.getTemplate();
	// Map<QuestEventType, Quest[]> map = npct.getEventQuests();
	// int type = L2Radar.GEN_NPC;
	// if (map != null) {
	// for (Map.Entry<QuestEventType, Quest[]> entry : map.entrySet()) {
	// Quest[] qls = entry.getValue();
	// for (int i = qls.length - 1; i >= 0; i--) {
	// Quest q = qls[i];
	// String qName = q.getName();
	// if (_mayAccepyQuestList.contains(qName)) {
	// if (q.getQuestDataSet().getStartNpcId() == npc.getTemplate()._id)
	// type = L2Radar.ACCEPTNPC;// !,有任务可接
	// }
	// if (_accepyQuestList.contains(qName)) {
	// if (getQuestState(qName).getState() == State.SUCCEED) {
	// if (q.getQuestDataSet().getEndNpcId() == npct._id)
	// type = L2Radar.RETURNNPC;// ?,有任务可交还(结束npc)
	// else
	// type = L2Radar.UNSUCCESS;// ?(灰色),已接没完成
	// } else {
	// type = L2Radar.UNSUCCESS;// ?(灰色),已接没完成
	// }
	// return type;
	// }
	//						
	// QuestState s = getQuestState(qName);
	// if (s != null && s.isCompleted()) { //-- 任务完成
	// type = L2Radar.GEN_NPC;
	// }
	// }
	// }
	// }
	// return type;
	// } else {
	// _log.warn("FuzePcInstance.getNpcQuestFace NPC  is null", getObjectId(),
	// "玩家任务表情");
	// }
	// return -1;
	// }

	public int getNpcQuestFace(L2Npc npc) {
		if (npc != null) {
			NpcTemplate npct = npc.getTemplate();
			Map<QuestEventType, Quest[]> map = npct.getEventQuests();
			int type = L2Radar.GEN_NPC;
			if (map != null) {
				for (Map.Entry<QuestEventType, Quest[]> entry : map.entrySet()) {
					Quest[] qls = entry.getValue();
					for (int i = qls.length - 1; i >= 0; i--) {
						Quest q = qls[i];
						String qName = q.getName();

						if (_mayAccepyQuestList.contains(qName)) { // --
							// 在可接任务列表内
							if (q.getQuestDataSet().getStartNpcId() == npc.getTemplate()._id)
								type = L2Radar.ACCEPTNPC;// 黄色!,有任务可接
						}

						if (_accepyQuestList.contains(qName)) { // -- 在已接任务列表内
							if (getQuestState(qName).getState() == State.SUCCEED) { // --
								// 任务已接
								if (q.getQuestDataSet().getStartNpcId() != q.getQuestDataSet().getEndNpcId()) { // --
									// 接受任务和归还任务NPC是否相同
									if (q.getQuestDataSet().getEndNpcId() == npct._id) {
										type = L2Radar.RETURNNPC;// 黄色?,有任务可交还(结束npc)
									} else {
										type = L2Radar.GEN_NPC; // -- 不显示图标
									}
								} else { // -- 接受NPC和归还NPC是同一NPC
									type = L2Radar.RETURNNPC; // -- 黄色?
									// 有任务等待交还,任务进行中
								}
							} else if (getQuestState(qName).getState() == State.STARTED) { // --
								// 任务开始
								if (q.getQuestDataSet().getStartNpcId() != q.getQuestDataSet().getEndNpcId()) { // --
									// 接受任务NPC和归还任务NPC不相同
									if (q.getQuestDataSet().getEndNpcId() == npct._id) { // --
										// 交还任务
										type = L2Radar.UNSUCCESS; // -- 有任务交还
									} else { // --
										type = L2Radar.GEN_NPC; // --
										// 接受任务NPC表情置空
									}
								} else { // -- 接受任务NPC和归还任务NPC是同一NPC
									type = L2Radar.UNSUCCESS;// ?(灰色),已接未完成
								}
							} else if (getQuestState(qName).getState() == State.COMPLETED) { // --
								// 任务开始
								if (q.getQuestDataSet().getStartNpcId() != q.getQuestDataSet().getEndNpcId()) { // --
									// 接受任务NPC和归还任务NPC不相同
									if (q.getQuestDataSet().getEndNpcId() == npct._id) { // --
										// 交还任务
										type = L2Radar.RETURNNPC; // -- 有任务交还
									} else { // --
										type = L2Radar.GEN_NPC; // --
										// 接受任务NPC表情置空
									}
								} else { // -- 接受任务NPC和归还任务NPC是同一NPC
									type = L2Radar.RETURNNPC;// ?(黄色),已接完成
								}
							} else {
							}

							return type;
						}
					}
				}
			}
			return type;
		} else {
			_log.warn("FuzePcInstance.getNpcQuestFace NPC  is null", getObjectId(), "玩家任务表情");
		}
		return -1;
	}

	/**
	 * 获取npc对玩家任务表情 增加传出任务是否完成参数
	 * 
	 * @param npc
	 * @param isQuestComplete
	 * @return
	 */
	public int getNpcQuestFace(L2Npc npc, QuestCompletedStatus isQuestComplete) {
		if (npc != null) {
			NpcTemplate npct = npc.getTemplate();
			Map<QuestEventType, Quest[]> map = npct.getEventQuests();
			int type = L2Radar.GEN_NPC;

			if (map != null) {
				for (Map.Entry<QuestEventType, Quest[]> entry : map.entrySet()) {
					Quest[] qls = entry.getValue();
					for (int i = qls.length - 1; i >= 0; i--) {
						Quest q = qls[i];
						String qName = q.getName();

						if (_mayAccepyQuestList.contains(qName)) { // --
							// 在可接任务列表内
							if (q.getQuestDataSet().getStartNpcId() == npc.getTemplate()._id)
								type = L2Radar.ACCEPTNPC;// 黄色!,有任务可接
						}

						if (_accepyQuestList.contains(qName)) { // -- 在已接任务列表内
							if (getQuestState(qName).getState() == State.SUCCEED) { // --
								// 任务已接
								if (q.getQuestDataSet().getStartNpcId() != q.getQuestDataSet().getEndNpcId()) { // --
									// 接受任务和归还任务NPC是否相同
									if (q.getQuestDataSet().getEndNpcId() == npct._id) {
										type = L2Radar.RETURNNPC;// 黄色?,有任务可交还(结束npc)
									} else {
										type = L2Radar.GEN_NPC; // -- 不显示图标
									}
								} else { // -- 接受NPC和归还NPC是同一NPC
									type = L2Radar.RETURNNPC; // -- 黄色?
									// 有任务等待交还,任务进行中
								}

							} else if (getQuestState(qName).getState() == State.STARTED) { // --
								// 任务开始
								if (q.getQuestDataSet().getStartNpcId() != q.getQuestDataSet().getEndNpcId()) { // --
									// 接受任务NPC和归还任务NPC不相同
									if (q.getQuestDataSet().getEndNpcId() == npct._id) { // --
										// 交还任务
										type = L2Radar.UNSUCCESS; // -- 有任务交还
									} else { // --
										type = L2Radar.GEN_NPC; // --
										// 接受任务NPC表情置空
									}
								} else { // -- 接受任务NPC和归还任务NPC是同一NPC
									type = L2Radar.UNSUCCESS;// ?(灰色),已接未完成
								}
							} else if (getQuestState(qName).getState() == State.COMPLETED) { // --
								// 任务开始
								if (q.getQuestDataSet().getStartNpcId() != q.getQuestDataSet().getEndNpcId()) { // --
									// 接受任务NPC和归还任务NPC不相同
									if (q.getQuestDataSet().getEndNpcId() == npct._id) { // --
										// 交还任务
										type = L2Radar.RETURNNPC; // -- 有任务交还
									} else { // --
										type = L2Radar.GEN_NPC; // --
										// 接受任务NPC表情置空
									}
								} else { // -- 接受任务NPC和归还任务NPC是同一NPC
									type = L2Radar.RETURNNPC;// ?(黄色),已接完成
								}
							} else {
							}
							return type;
						}

						QuestState s = getQuestState(qName);
						if (s != null && s.isCompleted()) { // -- 任务完成时设置表情图标为空
							isQuestComplete.setHasCompleted(true); // --
							// 将任务完成状态值传出
							type = L2Radar.GEN_NPC;
						}
					}
				}
			}
			return type;
		} else {
			_log.warn("FuzePcInstance.getNpcQuestFace NPC  is null", getObjectId(), "玩家任务表情");
		}
		return -1;
	}

	/**
	 * 保存任务事件,这里只是保存玩家相关事件,和npc无关<br>
	 * 保证玩家的任务状态正确 2010-5-13
	 * 
	 * @author lyh
	 */
	public void saveQuestEvent() {
		Map<QuestEventType, Set<String>> em = this.getQuestEvents();
		List<FuzePcInstance.PlayerQuestValues> list = this.getQuestValues();
		if (list != null) {
			for (Iterator<PlayerQuestValues> itr = list.iterator(); itr.hasNext();) {// 先清空原有事件
				PlayerQuestValues pqv = itr.next();
				if (pqv.getVal().equals("<events>"))
					itr.remove();
			}
		}
		if (em != null) {
			for (Map.Entry<QuestEventType, Set<String>> entry : em.entrySet()) {// 保存玩家相关事件
				QuestEventType event = entry.getKey();
				Set<String> set = entry.getValue();
				for (Iterator<String> itr = set.iterator(); itr.hasNext();) {
					String name = itr.next();
					FuzePcInstance.PlayerQuestValues pqv = newPlayerQuestValues(name, "<events>", event.getName());
					this.getQuestValues().add(pqv);
				}

			}
		}
	}

	/**
	 * 过滤npc可接任务列表
	 * 
	 * @param options
	 *            npc 可选任务列表 2010-5-24
	 * @author lyh
	 */
	public void filterNpcQuestList(List<Quest> options) {
		Iterator<Quest> itr = options.iterator();
		while (itr.hasNext()) {
			Quest q = itr.next();
			String name = q.getName();
			if (!_mayAccepyQuestList.contains(name) && !_accepyQuestList.contains(name)) {
				itr.remove();
			}
		}
	}

	//是否能被其他较深色攻击的状态
	private boolean _isAttackByPc = true;

	public boolean isAttackByPc() {
		return _isAttackByPc;
	}

	public void setAttackByPc(boolean isAttackByPc) {
		_isAttackByPc = isAttackByPc;
	}

}
